一起养成写作习惯!这是我参与「掘金日新计划 · 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的实例
首先通过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链列表中
通知器链初始化完后,获取Bean实例
判断使用JDK动态代理还是CGLIB代理,得到AopProxy对象后,通过调用AopProxy.getProxy()方法就能得到代理对象,
有了代理对象以后,当调用代理对象的方法时则会被增强,这里我们重点分析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动态代理实现的基本框架代码,当然具体的实现肯定比这个复杂得多。