JDK代理和CGLIB代理
学而时习之,不亦说乎!
--《论语》
AOP是spring的一个重要组成部分,而AOP通过代理实现。这儿写下JDK代理和CGLIB代理两种动态代理,为接下来的Spring AOP做准备。
JDK代理:
1)项目整体结构如下:
2)创建maven项目,pom.xml如下:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zby</groupId> <artifactId>aop</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency> </dependencies> </project>
这个依赖主要是给CGLIB用的,JDK代理并不需要。
3)创建UserService接口:
package com.zby.service; public interface UserService { void saveUser(String username, String password); }
4)创建UserService接口实现类UserServiceImpl:
package com.zby.service.impl; import com.zby.service.UserService; public class UserServiceImpl implements UserService { public void saveUser(String username, String password) { System.out.println("save user[username=" + username + ",password=" + password + "]"); } }
5)创建CustomAspect切面类:
package com.zby.aspect; public class CustomAspect { public void startTransaction() { System.out.println("I get datasource here and start transaction"); } public void endTrasaction() { System.out.println("I get datasource here and end transaction"); } }
6)创建JDKProxy代理工厂:
package com.zby.factory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.zby.aspect.CustomAspect; public class JDKProxy { public static Object createProxy(final Object targetObj, final CustomAspect customAspect) { // 使用JDK的Proxy类为目标类创建代理对象 return Proxy.newProxyInstance( // 目标类使用的类加载器 targetObj.getClass().getClassLoader(), // 目标类实现的接口 targetObj.getClass().getInterfaces(), // 执行处理器,代理我们的业务逻辑 new InvocationHandler() { public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 执行切面方法 customAspect.startTransaction(); // 具体逻辑代码执行,返回值为方法执行结果 Object result = method.invoke(targetObj, args); // 执行切面方法 customAspect.endTrasaction(); // 返回方法执行结果 return result; } }); } }
7)编写测试代码:
package com.zby.test; import org.junit.Test; import com.zby.aspect.CustomAspect; import com.zby.factory.JDKProxy; import com.zby.service.UserService; import com.zby.service.impl.UserServiceImpl; public class JDKProxyTest { @Test public void testJDKProxy() { System.out.println("before Proxy......"); UserService userService = new UserServiceImpl(); userService.saveUser("zby", "1234567890"); System.out.println("After Proxy......"); UserService proxyUserService = (UserService)JDKProxy.createProxy(userService, new CustomAspect()); proxyUserService.saveUser("zby", "1234567890"); } }
8)控制台打印结果:
before Proxy...... save user[username=zby,password=1234567890] After Proxy...... I get datasource here and start transaction save user[username=zby,password=1234567890] I get datasource here and end transaction
CGLIB代理:
1)使用JDK代理创建的UserService接口,UserServiceImpl实现类和CustomAspect切面类。
2)创建CGLIB的代理类CGLIBProxy:
package com.zby.factory; import java.lang.reflect.Method; import com.zby.aspect.CustomAspect; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CGLIBProxy { public static Object createProxy(final Object targetObj, final CustomAspect customAspect) { Enhancer enhancer = new Enhancer(); // 设置需要代理的父类 enhancer.setSuperclass(targetObj.getClass()); // 设置回调 enhancer.setCallback(new MethodInterceptor() { @Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { // 执行切面方法 customAspect.startTransaction(); // 具体逻辑代码执行,返回值为方法执行结果 Object result = methodProxy.invokeSuper(proxy, args); // 执行切面方法 customAspect.endTrasaction(); // 返回方法执行结果 return result; } }); // 3.4 创建代理 return enhancer.create(); } }
3)编写测试类:
package com.zby.test; import org.junit.Test; import com.zby.aspect.CustomAspect; import com.zby.factory.CGLIBProxy; import com.zby.service.UserService; import com.zby.service.impl.UserServiceImpl; public class CGLIBProxyTest { @Test public void testJDKProxy() { System.out.println("before Proxy......"); UserService userService = new UserServiceImpl(); userService.saveUser("zby", "1234567890"); System.out.println("After Proxy......"); UserService proxyUserService = (UserService) CGLIBProxy.createProxy(userService, new CustomAspect()); proxyUserService.saveUser("zby", "1234567890"); } }
4)控制台打印结果:
before Proxy...... save user[username=zby,password=1234567890] After Proxy...... I get datasource here and start transaction save user[username=zby,password=1234567890] I get datasource here and end transaction
5)CGLIB代理和JDK代理最大的区别就是:CGLIB代理的对象不需要实现任何接口,它使用的字节码子类代理方式,但是JDK代理的对象必须实现接口。这儿使用CGLIB代理的时候,可以将UserService删除,使用UserServiceImpl接收代理结果,效果完全一样。
6)JDK代理的实质是生成一个实现我们传入的接口,并且继承Proxy的类;Cglib代理实质是继承我们传入的类。