zoukankan      html  css  js  c++  java
  • Spring AOP的两种代理方式

    Spring AOP主要有两种代理方式:

    1.JDK动态代理  2.cglib代理
    1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
    2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
    3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
    注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好,具体原因请自行百度。

    一、JDK动态代理实现(原理是使用反射机制)
    1、定义TestService接口
    [java] view plain copy
    package io.mykit.proxy.jdk.service; 
     
    /**
     * JDK动态代理Service
     * @author liuyazhuang
     *
     */ 
    public interface TestService { 
         
        int add(); 

    2、定义TestServiceImpl实现类
    [java] view plain copy
    package io.mykit.proxy.jdk.service.impl; 
     
    import io.mykit.proxy.jdk.service.TestService; 
     
    public class TestServiceImpl implements TestService { 
     
        @Override 
        public int add() { 
            System.out.println("开始执行add..."); 
            return 0; 
        } 
     

    3、定义动态代理类JDKDynamicProxy
    [java] view plain copy
    package io.mykit.proxy.jdk.handler; 
     
    import java.lang.reflect.InvocationHandler; 
    import java.lang.reflect.Method; 
    import java.lang.reflect.Proxy; 
     
    /**
     * JDK的动态代理实现
     * @author liuyazhuang
     *
     */ 
    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("开始执行目标对象之后..."); 
        } 

    4、实现测试类ProxyTest
    [java] view plain copy
    package io.mykit.proxy.jdk; 
     
    import io.mykit.proxy.jdk.handler.JDKDynamicProxy; 
    import io.mykit.proxy.jdk.service.TestService; 
    import io.mykit.proxy.jdk.service.impl.TestServiceImpl; 
     
    /**
     * 动态代理测试
     * 
     * @author liuyazhuang
     *
     */ 
    public class ProxyTest { 
         
        public static void main(String[] args) { 
            // 我们要代理的真实对象 
            TestService testService = new TestServiceImpl(); 
            testService.add();// 不是用代理 
            System.out.println("==================================="); 
            JDKDynamicProxy JDKDynamicProxyTarget = new JDKDynamicProxy(); 
            TestService testServiceProxy = (TestService) JDKDynamicProxyTarget.newProxy(testService); 
            // 执行代理类的方法 
            testServiceProxy.add(); 
        } 

    5、测试结果如下
    [plain] view plain copy
    开始执行add... 
    =================================== 
    开始执行目标对象之前... 
    开始执行add... 
    开始执行目标对象之后... 
    二、CGLIB代理
    1、创建TestCGLIBServiceImpl类
    [java] view plain copy
    package io.mykit.proxy.cglib.service.impl; 
    /**
     * 未实现接口的类
     * @author liuyazhuang
     *
     */ 
    public class TestCGLIBServiceImpl { 
        public int add() { 
            System.out.println("开始执行add..."); 
            return 0; 
        } 
     } 
    2、创建代理类CGLIBProxy
    [java] view plain copy
    package io.mykit.proxy.cglib.handler; 
     
    import java.lang.reflect.Method; 
    import net.sf.cglib.proxy.Enhancer; 
    import net.sf.cglib.proxy.MethodInterceptor; 
    import net.sf.cglib.proxy.MethodProxy; 
     
    /**
     * 基于CGLIB实现
     * @author liuyazhuang
     *
     */ 
    public class CGLIBProxy implements MethodInterceptor { 
     
        private Object targetObject;// 被代理的目标对象 
     
        /**
         * 构造代理对象
         * @param targetObject 传递的真实对象
         * @return 代理对象
         */ 
        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; 
        } 

    3、创建测试类ProxyTest
    [java] view plain copy
    package io.mykit.proxy.cglib; 
     
    import io.mykit.proxy.cglib.handler.CGLIBProxy; 
    import io.mykit.proxy.cglib.service.impl.TestCGLIBServiceImpl; 
     
    /**
     * 测试CGLIB代理
     * @author liuyazhuang
     *
     */ 
    public class ProxyTest { 
         
         public static void main(String[] args) { 
             //我们要代理的真实对象 
             TestCGLIBServiceImpl testCGLIB = new TestCGLIBServiceImpl(); 
             testCGLIB.add(); 
             System.out.println("======================================"); 
             CGLIBProxy CGLIBproxy = new CGLIBProxy(); 
             TestCGLIBServiceImpl testCGLIBProxy = (TestCGLIBServiceImpl) CGLIBproxy.createProxyInstance(testCGLIB); 
             testCGLIBProxy.add(); 
          } 

    4、测试结果
    [plain] view plain copy
    开始执行add... 
    ====================================== 
    前置处理开始 ... 
    开始执行add... 
    后置处理开始  ... 
     调用结束 ... 
    5、pom.xml中添加的Jar包
    [html] view plain copy
    <properties> 
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> 
        <skip_maven_deploy>false</skip_maven_deploy> 
        <jdk.version>1.8</jdk.version> 
        <spring.version>4.1.0.RELEASE</spring.version> 
    </properties> 
     
    <dependencies> 
        
      <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-expression</artifactId> 
            <version>${spring.version}</version> 
        </dependency>  
         
            <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-messaging</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-jms</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-aop</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-jdbc</artifactId> 
             <version>${spring.version}</version> 
        </dependency> 
         
         <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-context</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
     
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-context-support</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-web</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.springframework</groupId> 
            <artifactId>spring-webmvc</artifactId> 
            <version>${spring.version}</version> 
        </dependency> 
         
        <dependency> 
            <groupId>org.aspectj</groupId> 
            <artifactId>aspectjtools</artifactId> 
            <version>1.9.1</version> 
        </dependency> 
         
        <dependency> 
            <groupId>javax.servlet</groupId> 
            <artifactId>javax.servlet-api</artifactId> 
            <version>3.0.1</version> 
        </dependency> 
     
        <dependency>   
            <groupId>org.slf4j</groupId>   
            <artifactId>slf4j-log4j12</artifactId>   
            <version>1.7.2</version>   
        </dependency>  
         
          <dependency> 
            <groupId>commons-logging</groupId> 
            <artifactId>commons-logging</artifactId> 
            <version>1.1.1</version> 
        </dependency> 
         <dependency> 
                <groupId>cglib</groupId> 
                <artifactId>cglib-nodep</artifactId> 
                <version>2.1_3</version> 
            </dependency> 
         
    </dependencies> 

  • 相关阅读:
    [centos6.5]添加eclipse快捷方式
    Maven 实用命令和技巧
    MyEclipse 15 集成SVN
    Eclipse不给提示no default proposals
    Eclipse快捷键
    Maven打包排除不需要的文件。
    MySQL用法
    Idea反向生成JavaBean
    java.lang.NoClassDefFoundError: [Lorg/hibernate/engine/FilterDefinition
    Spring+SpringMVC+MyBatis+Maven 服务端XML配置
  • 原文地址:https://www.cnblogs.com/zhuyeshen/p/12579162.html
Copyright © 2011-2022 走看看