AOP详解-动态代理实现AOP

98 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第10天,点击查看活动详情

之前我们已经介绍了aop的相关概念,接下来我们通过ProxyFactoryBean来深入分析Spring如何通过JDK动态代理实现AOP

动态代理特性

  • 继承了Proxy类,实现了代理的接口,由于java不能多继承,这里已经继承了Proxy类了,不能再继承其他的类,所以JDK的动态代理不支持对实现类的代理,只支持接口的代理。
  • 提供了一个使用InvocationHandler作为参数的构造方法。
  • 生成静态代码块来初始化接口中方法的Method对象,以及Object类的equals、hashCode、toString方法。
  • 重写了Object类的equals、hashCode、toString,它们都只是简单的调用了InvocationHandler的invoke方法
  • 代理类实现代理接口的sayHello方法中,只是简单的调用了InvocationHandler的invoke方法,我们可以在invoke方法中进行一些特殊操作,甚至不调用实现的方法,直接返回。

ProxyFactoryBean 分析

ProxyFactoryBean类是一个FactoryBean的Bean,也实现了BeanFactoryAware,因此在Spring初始化ProxyFactoryBean Bean的实例时,会将Spring的BeanFactory通过setBeanFactory(BeanFactory beanFactory) 赋值给beanFactory属性

由于ProxyFactoryBean是一个FactoryBean,因此提供了一个getObject()的Bean获取方法,通过此方法获取Bean的实例

image.png

首先通过this.initializeAdvisorChain();方法初始化通知器链AdvisorChain

通过解析interceptorNames指定的值获取通知器链,this.addAdvisorOnChainCreation(advice, name)

调用了DefaultAdvisorAdapterRegistry.wrap()

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
    if (!this.advisorChainInitialized) {
        if (!ObjectUtils.isEmpty(this.interceptorNames)) {
            if (this.beanFactory == null) {
                throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) - cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
            }

     ...
                    this.addAdvisorOnChainCreation(advice, name);
                }
            }
        }

        this.advisorChainInitialized = true;
    }
}

addAdvisorOnChainCreation将获取到的通知器链添加到Advisor链列表中

image.png

通知器链初始化完后,获取Bean实例

判断使用JDK动态代理还是CGLIB代理,得到AopProxy对象后,通过调用AopProxy.getProxy()方法就能得到代理对象,

image.png 有了代理对象以后,当调用代理对象的方法时则会被增强,这里我们重点分析JdkDynamicAopProxy.invoke()方法,处理回调

代码实现:

1、创建接口

public interface Subject {
    void request();
    void hello();
}

2、创建目标对象


public class RealSubject implements Subject {
    public void request() {
        System.out.println("real subject execute request..");
    }

    public void hello() {
        System.out.println("real subject execute hello..");
    }
}


3、创建代理对象

public class JdkProxySubject implements InvocationHandler {
    private RealSubject realSubject;


    public JdkProxySubject(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("before。。");
        Object result = null;
        try {
        
            result = method.invoke(realSubject,args);
        } catch (Exception e) {
            System.out.println("ex:" + e.getMessage());
            throw e;
        } finally {
            System.out.println("after..");
        }
        return result;
    }
}

4.客户端调用


public class Client {
    public static void main(String[] args) {

       /
        Subject subject = (Subject) java.lang.reflect.Proxy.newProxyInstance(Client.class.getClassLoader(), new Class[]{Subject.class}, new JdkProxySubject(new RealSubject()));
        subject.request();
        subject.hello();
    }
}


上面是对于Spring AOP使用JDK动态代理实现的基本框架代码,当然具体的实现肯定比这个复杂得多。