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> 



梅花香自古寒来