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> 

posted @ 2020-03-27 08:47  那些年的代码  阅读(4643)  评论(0编辑  收藏  举报