AOP 中的代理就是由 AOP 框架动态生成的一个对象,该对象可以作为目标对象使用。Spring 中的 AOP 代理,可以是 JDK 动态代理,也可以是 CGLIB代理。
jdk代理
JDK 动态代理是通过 java.lang.reflect.Proxy
类来实现的,我们可以调用 Proxy 类的 newProxylnstance()
方法来创建代理对象。 对于使用业务接口的类, Spring默认会使用 JDK 动态代理来实现 AOP。
实现jdk动态代理,准备工作是要导入Spring相关的包,不会的话可以参考:Spring包的下载 和 配置环境
随后创建一个接口,给接口定义俩个方法。
package jdk动态代理;
public interface UserDao {
public void addUser();
public void deleteUser();
}
再创建UserDao
接口的实现类UserDaolmpl
分别实现接口中的方法,并在每个方法中添加一条输出语句,
package jdk动态代理;
public class UserDaolmpl implements UserDao {
public void addUser() {
System.out.println("添加");
}
public void deleteUser() {
System.out.println("删除");
}
}
创建切面类MyAspect,在该类中定义一个模拟权限检查的方法和一个模拟记录日志的方法,这两个方法就表示切面中的通知
package jdk动态代理;
public class MyAspect {
public void check_Permissions() {
System.out.println("模拟检查权限. . . ");
}
public void log() {
System.out.println("模拟记录日志. . . ");
}
}
创建代理类 JdkProxy,该类需要实现InvocationHandler
接口,并编写代理方法。 在代理方法中,需要通过Proxy类实现动态代理,
JdkProxy 类实现了InvocationHandler
接口,并实现了接口中的 invoke()
方法,所有动态代理类所调用的方法都会交由该方法处理。 在创建的代理方法createProxy()
中, 使用了 Proxy 类的newProxylnstance()
方法来创建代理对象。newProxylnstance()
方法中包含3个参数,其中第 1 个参数是当前类的类加载器,第2个参数表示的是被代理对象实现的所有接口, 第3个参数this代表的就是代理类JdkProxy本身。在 invoke()
方法中,目标类方法执行的前后,会分别执行切面类中的 check_Permissions()
方法和 log()
方法。
package jdk动态代理;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler {
// 声明目标类接口
private UserDao userDao;
// 创建代理方法
public Object createProxy(UserDao userDao) {
this.userDao = userDao;
// 1.类加载器
ClassLoader classLoader = JdkProxy.class.getClassLoader();
// 2.被代理对象实现的所有接口
Class[] clazz = userDao.getClass().getInterfaces();
// 3.使用代理类,进行增强j 返回的是代理后的对象
return Proxy.newProxyInstance(classLoader, clazz, this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//声明切面
MyAspect myAspect = new MyAspect();
//前增强
myAspect.check_Permissions();
//在目标类上调用方法,并传入参数
Object obj = method.invoke(userDao, args);
//后增强
myAspect.log();
return obj;
}
}
最后定义一个测试类,在该类中的 mainO方法中创建代理对象和目标对象,然后从代理对象中获得对目标对象userDao增强后的对象,最后调用该对象中的添加和删除方法
package jdk动态代理;
public class JdkTest {
public static void main(String[] args) {
JdkProxy jdkproxy = new JdkProxy();
// 创建目标对象
UserDao userDao = new UserDaolmpl();
// 从代理对象中获取增强后的日标对象
UserDao userDao1 = (UserDao) jdkproxy.createProxy(userDao);
userDao1.addUser();
userDao1.deleteUser();
}
}
CGLIB代理
JDK 动态代理的使用非常简单,但它还有一定的局限性一一使用动态代理的对象必须实现一 个或多个接口 。 如果要对没有实现接口的类进行代理,那么可以使用 CGL旧代理。
CGL旧( Code Generation Library )是一个高性能开源的代码生成包,它采用非常底层的字 节码技术,对指定的目标类生成一个子类,并对子类进行增强。在Spring的核心包中已经集成 了 CGL旧所需要的包,所以开发中不需要另外导入 JAR 包。
首先创建一个目标类 UserDao
, UserDao
不需要实现任何接口,只需定义一个添加用户的方法和一个删除用户的方法,
package Cglib代理;
public class UserDao {
public void addUser() {
System.out.println("添加");
}
public void deleteUser() {
System.out.println("删除");
}
}
创建代理类 CglibProxy,该代理类需要实现 MethodInterceptor
接口,并实现接口中的 intercept()
方法,
首先创建了一个动态类对象Enhancer
,它是CGL旧的核心类;然后 调用了Enhancer类的 setSuperclass()
方法来确定目标对象;接下来调用了 setCallback()
方法添加回调函数,其中的 this 代表的就是代理类CglibProxy
本身;最后通过 return
语句将创建的代理类对象返 回。 intercept()
方法会在程序执行目标方法时被调用,方法运行时将会执行切面类中的增强方法。
package Cglib代理;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
import org.springframework.cglib.proxy.MethodInterceptor;
import jdk动态代理.MyAspect;
public class CglibProxy implements MethodInterceptor { // 创建代理类
public Object createProxy(Object target) {// 代理方法
// 创建一个动态类对象
Enhancer enhancer = new Enhancer();
// 确定需要增强的类,设置其父类
enhancer.setSuperclass(target.getClass());
// 添加回调函数
enhancer.setCallback(this);
// 返回创建的代理类
return enhancer.create();
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
// 创建切面类对象
MyAspect myAspect = new MyAspect();
// 前增强
myAspect.check_Permissions();
// 目标方法执行
Object obj = methodProxy.invokeSuper(proxy, args);
// 后增强
myAspect.log();
return obj;
}
}
创建测试类CglibTest。在该类的main()方法中首先创建代 理对象和目标对象,然后从代理对象中获得增强后的目标对象,最后调用对象的添加和删除方法,
package Cglib代理;
public class CglibTest {
public static void main(String[] args) {
CglibProxy cglibproxy = new CglibProxy();
// 创建目标对象
UserDao userDao = new UserDao();
// 从代理对象中获取增强后的日标对象
UserDao userDao1 = (UserDao) cglibproxy.createProxy(userDao);
userDao1.addUser();
userDao1.deleteUser();
}
}