学而时习之,不亦说乎!
--《论语》
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代理实质是继承我们传入的类。