前提知识:动态代理
基于接口的配置方式
基于接口的配置方式比较古老,但是有利于熟悉源码。
一个简单的例子:
1.StudentService接口,里面包含了一个save方法:
1 | public interface StudentService { |
2.StudentService接口实现类StduentServiceImpl,它实现了save方法,里面只是简单的打印了一句话:
1 | public class StudentServiceImpl implements StudentService{ |
3.一个自定义前置通知器MyBeforeAdvide,它实现了方法前置通知器接口MethodBeforeAdvice,重写了before方法:
1 | public class MyBeforeAdvice implements MethodBeforeAdvice { |
4.创建spring-aop.xml配置文件,添加以下配置:
1 | <?xml version="1.0" encoding="UTF-8"?> |
5.单元测试:
1 | public class MyBeforeAdviceTest { |
运行结果:
1 | 准备调用方法:save |
可以看到在save方法执行之前,首先执行了自定义通知器中的before方法。
参考:
ProxyFactoryBean生成AopProxy代理对象
1.ProxyFactoryBean
从上面例子看到,配置代理的时候使用的是ProxyFactoryBean,那么就从ProxyFactoryBean开始,看一下AOP的实现原理。
1 | public class ProxyFactoryBean extends ProxyCreatorSupport |
(1)ProxyFactoryBean中的getObject方法,首先对通知器链进行初始化,通知器链封装了一系列的拦截器,这些拦截器从XML配置文件中读取,为代理对象的生成做好准备。
配置文件中的拦截器interceptorNames:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60<!--配置代理-->
<bean id="studentServiceProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<!--代理的接口-->
<value>com.study.proxybeanfactory.StudentService</value>
</property>
<!--代理的具体实现-->
<property name="target" ref="studentService"></property>
<!--配置拦截器,配置定义的通知器-->
<property name="interceptorNames">
<list>
<value>myAdvice</value>
</list>
</property>
</bean>
```
(2)advisor通知器的获取是通过IoC容器的getBean(name)方法完成的。
(3)在初始化拦截器链initializeAdvisorChain方法中,需要对bean是prototype还是singleton进行判断,如果是singleton直接根据bean的名字通过容器的getBean方法获取即可,如果是prototype,创建PrototypePlaceholderAdvisor。
回到getObject方法,看一下生成singleton的代理对象的过程,生成singlton代理对象的方法在getSingletonInstance()方法中完成:
``` java
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
//设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
super.setFrozen(this.freezeProxy);
//生成代理
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
/**
* 创建AOP代理
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
/**
* 通过创建的AopProxy获取代理
*/
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
(1)在createAopProxy()方法创建了AOP代理,方法的返回类型是AopProxy,它是一个接口,它有两个子类CglibAopProxy和JdkDynamicAopProxy,从名字上就可以看出来CglibAopProxy是通过CGLIB来生成代理对象,JdkDynamicAopProxy使用JDK动态代理生成代理对象。
1 | final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {} |
(2)createAopProxy()方法是在ProxyCreatorSupport中完成的。
2.ProxyCreatorSupport
1 | public class ProxyCreatorSupport extends AdvisedSupport { |
在createAopProxy方法中,通过获取Aop代理工厂AopProxyFactory创建Aop代理对象,AopProxyFactory是一个接口,ProxyCreatorSupport的构造函数中可以看到,工厂使用DefaultAopProxyFactory实现。
1 | public interface AopProxyFactory { |
3.Aop代理工厂DefaultAopProxyFactory
1 | public class DefaultAopProxyFactory implements AopProxyFactory, Serializable { |
生成代理对象的过程中,需要从AdvisedSupport对象中获取配置的目标对象,对目标对象配置的检查完成后,根据配置的情况决定使用什么方式创建AopProxy代理对象。如果目标对象是接口类的实现,使用JDK动态代理,否则使用CGLIB生成。
JDK生成Aop代理对象
JdkDynamicAopProxy本身实现了InvocationHandler接口,所以使用Proxy.newProxyInstance方法生成对象时可以将自身指派给代理对象。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
//使用JDK动态代理生成代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
}
CGLIB生成Aop代理对象
1 | class CglibAopProxy implements AopProxy, Serializable { |
到这里,AopProxy对象已经生成了,通过ProxyFactoryBean的getObject方法获取到的对象就不是一个普通的Java对象了,而是一个AopProxy代理对象,当调用目标对象的方法时,会被AopProxy代理对象拦截,对于JDK动态代理,使用的是InvocationHandler的invoke回调入口;对于Cglib,使用的是设置好的callback回调。
参考:
spring技术内幕:深入解析spring架构与设计原理
【Spring源码–AOP的实现】(一)AopProxy代理对象的创建
Spring版本:5.0.5