Spring核心技术AOP实现原理
关于Spring的AOP也是Spring的非常重要的一项技术。大致上可以这样说,面向切面编程,它的出现说明可以在不修改代码的情况下实现对功能的增强。而增强就是给一个方法增加一些功能。AOP主要思想就是把增强的代码可以单独写成一个方法。比如说想对某个方法增加一个检测权限的功能,就可以单独写成一个checkPrivilege方法。可以在需要被增强的方法执行之前,自动的让checkPriviliege方法执行,就像在这个方法前形成一个切面,在切面出安装一个checkPriviliege方法。最终在没有修改源代码的情况下实现功能增强了。这就是它的一个思想,其Spring中的AOP实现有两种方式。分别是JDK代理和Cglib代理。先说说JDK代理:它只能对实现接口的类产生代理。
接口:
public interface PostCard { public void soup(); }
类实现以上接口:
@Service("postCard") public class PostCardImpl implements PostCard{ public void soup() { System.out.println("我是postcard..."); } }
创建代理类,该类必须要实现InvocationHandler接口,代码如下:
/* * 动态代理实现 * */ public class JdkProxy implements InvocationHandler{ private PostCard postCard; //增强的目标 /* * 构造方法 * */ public JdkProxy(PostCard postCard) { super(); this.postCard = postCard; } /* * 利用JDK代理动态生成对象的方法 * newProxyInstance的三个参数 * loader:目标类的加载器 * interfaces:目标类所实现的接口 * handler:回调 * */ public PostCard create(){ PostCard proxy = (PostCard) Proxy.newProxyInstance(postCard.getClass().getClassLoader(), postCard.getClass().getInterfaces(), this); return proxy; } /* * 执行目标对象的方法 * */ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("检测功能before"); // 调用目标方法 Object result = method.invoke(postCard, args); System.out.println("检测功能after"); return result; } }
测试:
@Test public void test() { // 实例化目标对象 PostCard cardImpl = new PostCardImpl(); // 实例化代理对象 JdkProxy proxy = new JdkProxy(cardImpl); // 生成代理对象 PostCard create = proxy.create(); // 调用代理对象方法 create.soup(); }
而cglib对象则是对没有实现接口类的增强,JDK代理无法做到这一点。cglib代理就是生成目标类的子类来增强。如下为案例,复用以上的类无须实现接口。然后创建cglib代理类,代码如下:
//代理类 public class CglibProxy implements MethodInterceptor{ /* * 调用构造函数的时,将类对象创建出来 * */ private PostCard postCard; //增强的目标 public CglibProxy(PostCard postCard){ this.postCard=postCard; } // 利用cglib生成代理对象 public PostCard create(){ // 创建cglib的核心对象 Enhancer enhancer = new Enhancer(); // 设置父类 enhancer.setSuperclass(postCard.getClass()); // 设置回调 enhancer.setCallback(this); // 创建代理对象 PostCard proxy = (PostCard) enhancer.create(); return proxy; } /* * 调用目标方法时,实质上就是调用该方法 * 参数1:代理对象 * 参数2:目标方法 * 参数3:目标方法的形参 * 参数4:代理方法 * */ public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { // 添加检测权限的方法 System.out.println("检测权限cglib..."); // 调用目标父类方法 Object object = arg3.invokeSuper(arg0, arg2); return object; } }
测试代码如下:
@Test public void test1() { // 目标 PostCard impl = new PostCardImpl(); // 实例化代理对象 CglibProxy cglibProxy = new CglibProxy(impl); // 生成代理对象 PostCard create = cglibProxy.create(); // 调用代理对象的方法 create.soup(); }
以上就是这2种代理的区别,SpringAOP编程就是利用的代理方法实现切面编程。
今天要比昨天好