首页 > 技术文章 > Spring核心技术AOP实现原理

lichangyun 2018-09-18 13:52 原文

关于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编程就是利用的代理方法实现切面编程。

推荐阅读