Apache commons Proxy简介和动态代理、动态拦截器实现

Apache Commons Proxy 是Apache 的一个之项目,封装了 Java 对象代理的一些常用方法。又叫做 动态代理。

动态代理的作用非常大,在很多底层框架中都会用得到,比如struts,Spring等都用到了动态代理,它的原理很简单,就是将你要使用的类,重新生成一个子类或本类,这样框架就可以利用这个新生成的类做一些事情,比如在该类的方法前后加一些代码。

设想一下,不用修改任何已经编写好的代码,只要使用动态代理就可以灵活的加入一些东西,将来要是不喜欢了,不用也不会影响原来的代码。

Apache Commons Proxy 的案例在网上找了很久,有用的资料实在不多,刚好JAVA也自带了动态代理,从JAVA的动态代理看起吧。

 

接口类

package test.ffm83.commons.proxy;

/**

 * 定义一个接口,一个方法

 * @author 范芳铭

 */

public interface BusinessProcessor {

         public voidprocessBusiness();

}

 

接口实现类

package test.ffm83.commons.proxy;

/**

 * 定义一个类,实现接口

 * @author 范芳铭

 */

public class BusinessProcessorImpl implements BusinessProcessor {

 

         @Override

         public voidprocessBusiness() {

                   // TODOAuto-generated method stub

                   System.out.println("执行处理逻辑单元.....");

         }

}

 

动态代理类

package test.ffm83.commons.proxy;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

/**

 * 实现InvocationHandler接口,为对象提供代理(代理类)

 * @author 范芳铭

 */

public class BusinessProcessorHandler implements InvocationHandler {

         private Object target =null;

        

         BusinessProcessorHandler(Objecttarget) {

                   this.target =target;

         }

 

         public Objectinvoke(Object proxy, Method method, Object[] args)

                            throws Throwable{

                   System.out

                                     .println("在执行你的逻辑模块之 前,随便做点什么吧。");

                   Object result =method.invoke(target, args);

                   System.out

                                     .println("在执行你的逻辑模块之 后,做点想做的事情吧。");

                   return result;

         }

}

 

动态代理调用类

package test.ffm83.commons.proxy;

 

import java.lang.reflect.Proxy;

/**

 * 测试这个代理类

 * @author 范芳铭

 */

public class BusinessProcessorTest {

         public static voidmain(String[] args) {

                   BusinessProcessorImplbpimpl = new BusinessProcessorImpl();

                   BusinessProcessorHandlerhandler = new BusinessProcessorHandler(bpimpl);

                   //这是动态代理的核心方法

                   BusinessProcessorbp = (BusinessProcessor) Proxy.newProxyInstance(

                                     bpimpl.getClass().getClassLoader(),bpimpl.getClass()

                                                        .getInterfaces(),handler);

                   bp.processBusiness();

         }

}

 

运行结果如下:

在执行你的逻辑模块之 前,随便做点什么吧。

执行处理逻辑单元.....

在执行你的逻辑模块之 后,做点想做的事情吧。

 

是不是有一种似曾相识的感觉,如果在前面加一段安全认证,后面加一段log记录,是不是有点spring之类的味道了?是不是有一种面向切面编程的感觉。

恭喜,确实如此。

 

学习了JAVA的动态拦截器的方法,那么用apache commons proxy的动态代理,就要简单不少。

用apache commons proxy 做一个简单的动态代理。

package test.ffm83.commons.proxy.util;

 

/**

 * 定义一个接口,一些方法

 * @author 范芳铭

 */

public interface Echo

{

    public String echoBack( Stringmessage );

    public String echoBack( Stringmessage1, String message2 );

    public String echoBack(String[] messages );

    public int echoBack( int i );

    public boolean echoBack(boolean b );

    public void echo();

}

 

package test.ffm83.commons.proxy.util;

 

/**

 * 简单实现接口方法

 * @author 范芳铭

 */

public class EchoImpl extends AbstractEcho

{

    public boolean echoBack(boolean b )

    {

        return b;

    }

 

    public String echoBack( Stringmessage1, String message2 )

    {

        return message1 +message2;

    }

 

    public String echoBack(String[] messages )

    {

        final StringBuffer sb =new StringBuffer();

        for( int i = 0; i <messages.length; i++ )

        {

            String message =messages[i];

            sb.append( message );

        }

        return sb.toString();

    }

 

    public int echoBack( int i )

    {

        return i;

    }

 

    public void echo()

    {

    }

}

 

主体类

package test.ffm83.commons.proxy;

 

import java.lang.reflect.Method;

import org.apache.commons.proxy.Invoker;

import org.apache.commons.proxy.ProxyFactory;

import test.ffm83.commons.proxy.util.Echo;

/**

 * 利用commons proxy做一个简单的动态代理

 * @author 范芳铭

 */

public class CommonsProxyInvoker {

         private ProxyFactoryfactory;

         private static finalClass[] ECHO_ONLY = new Class[] { Echo.class };

 

         public static voidmain(String[] args) throws Exception {

                   CommonsProxyInvokerproxy = new CommonsProxyInvoker();

                   proxy.testInvokerProxy();

         }

 

         publicCommonsProxyInvoker() {

                   factory = newProxyFactory();

         }

 

         public voidtestInvokerProxy() throws Exception {

                   finalInvokerTester tester = new InvokerTester();

                   System.out.println("....在执行你的逻辑模块之 前,随便做点什么吧。");

                   final Echo echo= (Echo) factory.createInvokerProxy(tester, ECHO_ONLY);

                   echo.echoBack("hello");

                   System.out.println("tester.args[0]:"+ tester.args[0]);

                   echo.echoBack("2不2", "不2");

                   System.out.println("tester.args[0]和[1]:" + tester.args[0] + ","

                                     +tester.args[1]);

                   System.out.println("....在执行你的逻辑模块之 前,随便做点什么吧。");

         }

 

         private static classInvokerTester implements Invoker {

                   private Objectmethod;

                   private Object[]args;

                   private Objectproxy;

 

                   public Objectinvoke(Object proxy, Method method, Object[] args)

                                     throwsThrowable {

                            this.proxy= proxy;

                            this.method= method;

                            this.args= args;

                            returnnull;

                   }

         }

 

}

 

下面是用apache commons proxy实现简单的拦截器

package test.ffm83.commons.proxy;

 

import java.lang.reflect.Method;

 

import org.apache.commons.proxy.Interceptor;

import org.apache.commons.proxy.Invocation;

import org.apache.commons.proxy.ProxyFactory;

 

import test.ffm83.commons.proxy.util.Echo;

import test.ffm83.commons.proxy.util.EchoImpl;

/**

 * 利用commons proxy做一个简单的动态代理拦截器

 * @author 范芳铭

 */

public class CommonsProxyInterceptor {

         private ProxyFactoryfactory;

         private static finalClass[] ECHO_ONLY = new Class[] { Echo.class };

        

         public static voidmain(String[] args) throws Exception {

                   CommonsProxyInterceptorproxy = new CommonsProxyInterceptor();

                   proxy.testMethodInvocationImplementation();

         }

        

         publicCommonsProxyInterceptor() {

                   factory = newProxyFactory();

         }

        

    public voidtestMethodInvocationImplementation() throws Exception

    {

        final InterceptorTestertester = new InterceptorTester();

        final EchoImpl target =new EchoImpl(); //实现类

        final Echo proxy = ( Echo) factory.createInterceptorProxy( target, tester, ECHO_ONLY );

        proxy.echo();

       System.out.println("tester.arguments :" + tester.arguments);

        System.out.println("tester.arguments.length:"+ tester.arguments.length);

       target.equals(tester.proxy);

 

        proxy.echoBack( "范芳铭" );

       System.out.println("tester.arguments :" + tester.arguments);

       System.out.println("tester.arguments.length:" +tester.arguments.length);

       System.out.println("tester.arguments[0]:" +tester.arguments[0]);

 

    }

   

    private static classInterceptorTester implements Interceptor

    {

        private Object[]arguments;

        private Method method;

        private Object proxy;

        private ClassinvocationClass;

 

        public Object intercept(Invocation methodInvocation ) throws Throwable

        {

            arguments =methodInvocation.getArguments();

            method = methodInvocation.getMethod();

            proxy =methodInvocation.getProxy();

            invocationClass =methodInvocation.getClass();

            returnmethodInvocation.proceed();

        }

    }

}

运行结果

tester.arguments :[Ljava.lang.Object;@2e7263

tester.arguments.length:0

tester.arguments :[Ljava.lang.Object;@157f0dc

tester.arguments.length:1

tester.arguments[0]:范芳铭

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。