转载请注明出处:https://blog.csdn.net/l1028386804/article/details/80295523
Spring AOP主要有两种代理方式:
1.JDK动态代理 2.cglib代理
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
注:JDK动态代理要比cglib代理执行速度快,但性能不如cglib好。所以在选择用哪种代理还是要看具体情况,一般单例模式用cglib比较好,具体原因请自行百度。
一、JDK动态代理实现(原理是使用反射机制)
1、定义TestService接口
package io.mykit.proxy.jdk.service; /** * JDK动态代理Service * @author liuyazhuang * */ public interface TestService { int add(); }
2、定义TestServiceImpl实现类
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
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
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、测试结果如下
开始执行add... =================================== 开始执行目标对象之前... 开始执行add... 开始执行目标对象之后...
二、CGLIB代理
1、创建TestCGLIBServiceImpl类
package io.mykit.proxy.cglib.service.impl; /** * 未实现接口的类 * @author liuyazhuang * */ public class TestCGLIBServiceImpl { public int add() { System.out.println("开始执行add..."); return 0; } }
2、创建代理类CGLIBProxy
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
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、测试结果
开始执行add... ====================================== 前置处理开始 ... 开始执行add... 后置处理开始 ... 调用结束 ...
5、pom.xml中添加的Jar包
<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>