Spring AOP的两种代理

本篇记录下Spring AOP的两种代理,为下一篇AOP实现做下铺垫。

1.JDK动态代理  2.cglib代理

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好,具体原因请自行百度。

一。JDK动态代理实现(原理是使用反射机制)

首先定义接口,并实现

      public interface TestService{

          public int add();   
      }

      public class TestServiceImpl implements TestService{

        @Override
        public int add() {
            System.out.println("开始执行add...");
            return 0;
        }
    }

定义代理类,这里要注意导入的包是import java.lang.reflect.*

  public class JDKDynamicProxy implements InvocationHandler {

    //被代理的目标对象
    private Object proxyObj; 
   
    /**
      * Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
      * loader    :类加载器 一个ClassLoader对象,定义了由哪个ClassLoader对象来对生成的代理对象进行加载
      * interfaces:一个Interface对象的数组,表示的是我将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了
      * h        :一个InvocationHandler对象,表示的是当我这个动态代理对象在调用方法的时候,会关联到哪一个InvocationHandler对象上
    */
      public Object newProxy(Object proxyObj){ 
            this.proxyObj = proxyObj;
            //返回一个代理对象 
          return Proxy.newProxyInstance(proxyObj.getClass().getClassLoader(), 
                                      proxyObj.getClass().getInterfaces(), 
                                      this); 
      } 

      /**
      * 执行目标对象
      * Object  proxy:被代理的对象
      * Method  method:要调用的方法
      * Object  args[]:方法调用时所需要的参数
      */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args)
                                  throws Throwable {     
            before();
            Object object = method.invoke(this.proxyObj,args);  // 通过反射机制调用目标对象的方法
            after();     
            return object; 
        }
   
        public void before(){
              System.out.println("开始执行目标对象之前...");
        }
   
        public void after(){
            System.out.println("开始执行目标对象之后...");
        }
    }

测试类:

      public static void main(String[] args) {
       
          //我们要代理的真实对象
          TestService testService = new TestServiceImpl();       
          //testJDKProxyService.add();//不是用代理   
       
        JDKDynamicProxy JDKDynamicProxyTarget = new JDKDynamicProxy();
        TestService testServiceProxy = (TestService) JDKDynamicProxyTarget.newProxy(testService);
        //执行代理类的方法 
        testServiceProxy.add();

    }

控制台显示

二。CGLIB代理,需要导入 cglib-nodep-2.1_3.jar

    先说下cglib,CGlib是一个强大的,高性能,高质量的Code生成类库。它可以在运行期扩展Java类与实现Java接口。

先定义一个实现类(注意并没有实现接口)

  public class TestCGLIBServiceImpl {

    public int add() {
        System.out.println("开始执行add...");
        return 0;
    }
 }

定义cglib代理类,此时导入的包应该是import net.sf.cglib.proxy.*

  import java.lang.reflect.Method;
  import net.sf.cglib.proxy.Enhancer;
  import net.sf.cglib.proxy.MethodInterceptor;
  import net.sf.cglib.proxy.MethodProxy;

    public class CGLIBProxy implements MethodInterceptor{

    private Object targetObject ;//被代理的目标对象
   
    public Object createProxyInstance(Object targetObject) {

          this . targetObject = targetObject;

          Enhancer enhancer = new Enhancer();

          enhancer.setSuperclass(targetObject.getClass());// 设置代理目标

          enhancer.setCallback( this );// 设置回调

          return enhancer.create();

    }
   

    /**
    * 在代理实例上处理方法调用并返回结果
    * @param object : 代理类
    * @param method :被代理的方法
    * @param args :该方法的参数数组
    * @param methodProxy
    */
    @Override
    public Object intercept(Object object, Method method, Object[] args,
            MethodProxy methodproxy) throws Throwable {       
        Object result = null;   
        try {
              System. out .println( "前置处理开始 ..." );
              result = methodproxy.invoke( targetObject , args);//执行目标对象的方法
              System. out .println( "后置处理开始  ..." );
          } catch (Exception e) {
              System. out .println( " 异常处理 ..." );
          } finally {
              System. out .println( " 调用结束 ..." );
          }
          return result;
      } 
  }
测试类:

  public class TestCGLIBProxy {

        public static void main(String[] args) {
       
          //我们要代理的真实对象
          TestCGLIBServiceImpl testCGLIB = new TestCGLIBServiceImpl();
          CGLIBProxy CGLIBproxy = new CGLIBProxy();
          TestCGLIBServiceImpl testCGLIBProxy = (TestCGLIBServiceImpl) CGLIBproxy.createProxyInstance(testCGLIB);
          testCGLIBProxy.add();
      }
  }

结果图:

写在后面:spring AOP的两种代理实现代码就写到这,这里只是实现了,如果你要想真正明白,还得熟悉其中原理机制,比如反射机制,newProxyInstance(...),Enhancer()原理,invoke()原理等等。

猜你喜欢

转载自www.linuxidc.com/Linux/2015-11/125017.htm
今日推荐