Spring,AOP,JDK动态代理、CGLIB代理
关于AOP的基本介绍,参考:Spring深入浅出(十二),AOP,AspectJ,基于XML开发
AOP的代理就是由AOP框架动态生成的一个对象,该对象可以作为目标对象使用。Spring中的AOP代理,可以是JDK动态代理,也可以是CGLIB代理(Code Generation Library)。
一、JDK动态代理
1. 创建接口
package com.itheima.jdk; public interface UserDao { public void addUser(); public void deleteUser(); }
2. 创建实现类
package com.itheima.jdk; import org.springframework.stereotype.Repository; // 目标类 @Repository("userDao") public class UserDaoImpl implements UserDao { public void addUser() { System.out.println("添加用户"); } public void deleteUser() { System.out.println("删除用户"); } }
3. 创建切面类
该类实现InvocationHandler接口,并实现接口中invoke()方法,所有动态代理类所调用的方法都会交由该方法处理。
package com.itheima.jdk; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.itheima.aspect.MyAspect; /** * JDK代理类 */ 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.使用代理类,进行增强,返回的是代理后的对象 return Proxy.newProxyInstance(classLoader, clazz, this); } /* * 所有动态代理类的方法调用,都会交由invoke()方法去处理 proxy 被代理后的对象 method 将要被执行的方法信息(反射) args * 执行方法时需要的参数 */ @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; } }
4. 创建主程序
package com.itheima.jdk; public class JdkTest { public static void main(String[] args) { // 创建代理对象 JdkProxy jdkProxy = new JdkProxy(); // 创建目标对象 UserDao userDao = new UserDaoImpl(); // 从代理对象中获取增强后的目标对象 UserDao userDao1 = (UserDao) jdkProxy.createProxy(userDao); // 执行方法 userDao1.addUser(); userDao1.deleteUser(); } }
5. 运行结果
模拟检查权限...
添加用户
模拟记录日志...
模拟检查权限...
删除用户
模拟记录日志...
二、CGLIB代理
使用JDK动态代理的对象必须实现一个或多个接口。如果要对没有实现接口的类进行代理,那么可以使用CGLIB代理。
1. 创建实现类
package com.itheima.cglib; //目标类 public class UserDao { public void addUser() { System.out.println("添加用户"); } public void deleteUser() { System.out.println("删除用户"); } }
2. 创建切面类
该代理类需要实现MethodInterceptor接口,并实现接口中的intercept方法。
package com.itheima.cglib; import java.lang.reflect.Method; import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import com.itheima.aspect.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(); } /** * proxy CGlib根据指定父类生成的代理对象 method 拦截的方法 args 拦截方法的参数数组 methodProxy * 方法的代理对象,用于执行父类的方法 */ @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; } }
3.创建主程序
package com.itheima.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(); } }
4. 输出结果
模拟检查权限...
添加用户
模拟记录日志...
模拟检查权限...
删除用户
模拟记录日志...
本文参考:《Java EE企业级应用开发教程》