AOP原理(一):AopProxy代理对象的生成

前提知识:动态代理

岑宇:Java的三种代理模式

孤傲苍狼:Java基础加强总结(三)——代理(Proxy)

基于接口的配置方式

基于接口的配置方式比较古老,但是有利于熟悉源码。

一个简单的例子:

1.StudentService接口,里面包含了一个save方法:

1
2
3
public interface  StudentService {
void save();
}

2.StudentService接口实现类StduentServiceImpl,它实现了save方法,里面只是简单的打印了一句话:

1
2
3
4
5
6
7
public class StudentServiceImpl implements StudentService{

@Override
public void save() {
System.out.println("执行save方法");
}
}

3.一个自定义前置通知器MyBeforeAdvide,它实现了方法前置通知器接口MethodBeforeAdvice,重写了before方法:

1
2
3
4
5
6
7
public class MyBeforeAdvice implements MethodBeforeAdvice {

@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("准备调用方法:" + method.getName());
}
}

4.创建spring-aop.xml配置文件,添加以下配置:

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
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd ">

<!--配置通知器-->
<bean id="myAdvice" class="com.study.proxybeanfactory.MyBeforeAdvice"/>

<!---配置bean-->
<bean id="studentService" class="com.study.proxybeanfactory.StudentServiceImpl"/>

<!--配置代理-->
<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>

</beans>

5.单元测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class MyBeforeAdviceTest {


@Test
public void testXMLConfig() {
//创建容器,加载配置文件
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/spring/spring-aop.xml");
//从容器中获取bean,注意这里,获取的是StduentService的代理,而不是studentServcie
StudentService studentService = (StudentService) applicationContext.getBean("studentServiceProxy");
//执行save方法,实际上是由代理完成的
studentService.save();
}
}

运行结果:

1
2
准备调用方法:save
执行save方法保存数据

可以看到在save方法执行之前,首先执行了自定义通知器中的before方法。

参考:

Spring AOP 使用介绍,从前世到今生


ProxyFactoryBean生成AopProxy代理对象

1.ProxyFactoryBean

从上面例子看到,配置代理的时候使用的是ProxyFactoryBean,那么就从ProxyFactoryBean开始,看一下AOP的实现原理。

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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
@Override
@Nullable
public Object getObject() throws BeansException {
//初始化通知器链
initializeAdvisorChain();
//如果是单例模式的bean
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}

/**
* 初始化通知器链
*/
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
}
//如果拦截器不为空
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));
}

// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}

// 遍历拦截器
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
}
//如果是全局的拦截器
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
//添加到全局拦截器
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}

else {
// 判断bean是singleton还是prototype
if (this.singleton || this.beanFactory.isSingleton(name)) {
// 根据bean的名字获取通知器
advice = this.beanFactory.getBean(name);
}
else {
// prototype类型的通知器
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
}
//初始化过之后设为true
this.advisorChainInitialized = true;
}

}

(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
2
3
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {}

class CglibAopProxy implements AopProxy, Serializable {}

(2)createAopProxy()方法是在ProxyCreatorSupport中完成的。

2.ProxyCreatorSupport

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
public class ProxyCreatorSupport extends AdvisedSupport {

private AopProxyFactory aopProxyFactory;

/**
* 构造函数
*/
public ProxyCreatorSupport() {
//这里可以看到代理工厂使用的是DefaultAopProxyFactory
this.aopProxyFactory = new DefaultAopProxyFactory();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//使用DefaultAopProxyFactory实现
return getAopProxyFactory().createAopProxy(this);
}

/**
* 获取AopProxyFactory
*/
public AopProxyFactory getAopProxyFactory() {
return this.aopProxyFactory;
}

在createAopProxy方法中,通过获取Aop代理工厂AopProxyFactory创建Aop代理对象,AopProxyFactory是一个接口,ProxyCreatorSupport的构造函数中可以看到,工厂使用DefaultAopProxyFactory实现。

1
2
3
4
5
6
7
8
public interface AopProxyFactory {

/**
* 根据配置信息创建AOP代理
*/
AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException;

}

3.Aop代理工厂DefaultAopProxyFactory

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
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {

@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
//从config中读取信息判断使用哪种方式生成代理
//如果使用显示优化或者配置了目标类
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
//获取目标对象
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//如果目标对象是接口
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
//使用JDK动态代理
return new JdkDynamicAopProxy(config);
}
//CGLIB生成代理
return new ObjenesisCglibAopProxy(config);
}
else {
//JDK动态代理
return new JdkDynamicAopProxy(config);
}
}

/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}

}

生成代理对象的过程中,需要从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
18
final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable {
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}

@Override
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
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
61
62
63
64
65
66
67
68
69
70
class CglibAopProxy implements AopProxy, Serializable {
@Override
public Object getProxy() {
return getProxy(null);
}

@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}

try {
//获取在IoC容器中配置的target对象
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");

Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}

// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);

// 创建并配置CGLIB的Enhancer
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
//设置Enhancer对象,包括设置代理接口、回调方法
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));

Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);

// 生成代理对象
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Throwable ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}

}

到这里,AopProxy对象已经生成了,通过ProxyFactoryBean的getObject方法获取到的对象就不是一个普通的Java对象了,而是一个AopProxy代理对象,当调用目标对象的方法时,会被AopProxy代理对象拦截,对于JDK动态代理,使用的是InvocationHandler的invoke回调入口;对于Cglib,使用的是设置好的callback回调。

参考:

spring技术内幕:深入解析spring架构与设计原理

【Spring源码–AOP的实现】(一)AopProxy代理对象的创建

Spring版本:5.0.5