1. Spring AOP示例代碼
示例代碼結(jié)構(gòu)如下圖所示:

其中切面類AspectObject的代碼:
@Aspect
@Component
public class AspectObject {
//抽取公共的切入點(diǎn)表達(dá)式
//1、本類引用
//2、其他的切面引用
@Pointcut("execution(public * io.zgc.spring.features.aop.annotation.TargetObject.*(..))")
public void pointCut(){};
//@Before在目標(biāo)方法之前切入;切入點(diǎn)表達(dá)式(指定在哪個(gè)方法切入)
@Before("pointCut()")
public void logStart(JoinPoint joinPoint){
Object[] args = joinPoint.getArgs();
System.out.println(""+joinPoint.getSignature().getName()+"運(yùn)行。。。@Before:參數(shù)列表是:{"+ Arrays.asList(args)+"}");
}
@After("io.zgc.spring.features.aop.annotation.AspectObject.pointCut()")
public void logEnd(JoinPoint joinPoint){
System.out.println(""+joinPoint.getSignature().getName()+"結(jié)束。。。@After");
}
//JoinPoint一定要出現(xiàn)在參數(shù)表的第一位
@AfterReturning(value="pointCut()",returning="result")
public void logReturn(JoinPoint joinPoint,Object result){
System.out.println(""+joinPoint.getSignature().getName()+"正常返回。。。@AfterReturning:運(yùn)行結(jié)果:{"+result+"}");
}
}
被代理類TargetObject的代碼:
@Component
public class TargetObject implements TargetInterface{
public String sayHello(String name) {
System.out.println("hello,"+name);
return "hello---"+name;
}
}
測試客戶端Client的代碼:
package io.zgc.spring.features.aop.annotation;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Client {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
TargetInterface bean = applicationContext.getBean(TargetInterface.class);
bean.sayHello("zgc");
System.out.println(bean.getClass().getName());
}
}
運(yùn)行測試代碼,輸入如下結(jié)果
sayHello運(yùn)行。。。@Before:參數(shù)列表是:{[zgc]}
hello,zgc
sayHello結(jié)束。。。@After
sayHello正常返回。。。@AfterReturning:運(yùn)行結(jié)果:{hello---zgc}
com.sun.proxy.$Proxy21
從輸出結(jié)果,可以看出TargetObject類,已經(jīng)被Spring修改成了代理類com.sun.proxy.$Proxy21并在sayHello方法執(zhí)行的織入了代理邏輯。接下來,我們就來分析下Spring是在什么地方以及通過什么方式將TargetObject替換成代理對象。
2. Debug調(diào)試
我們使用倒推的方式進(jìn)行debug,重點(diǎn)關(guān)注我們需要關(guān)注的代碼。
2.1. getBean調(diào)試
我們先假設(shè)代理對象實(shí)在獲取bean的時(shí)候發(fā)生的。
TargetInterface bean = applicationContext.getBean(TargetInterface.class);
Debug跟進(jìn)去發(fā)現(xiàn),它最終是在singletonObjects中將代理對象獲取出來的,而singletonObjects是個(gè)Map結(jié)構(gòu),它里面存放的是單例bean,可以簡單將其理解為bean工廠(tips:這種理解并不準(zhǔn)確)。

這里我們可以得出結(jié)論:代理對象的創(chuàng)建一定是包含在ApplicationContext對象創(chuàng)建的過程中。
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AopConfig.class);
那我們就在singletonObjects放置值的地方加上斷點(diǎn),再通過程序的調(diào)用棧嘗試查看代理對象在什么地方生成。

為了減低干擾,斷點(diǎn)需要加上條件beanName.equals("targetObject");
2.2. ApplicationContext創(chuàng)建debug
上面斷點(diǎn)設(shè)置后,我們重新運(yùn)行程序,可以看到以下程序調(diào)用棧

我們向上追溯一下調(diào)用棧上的代碼,調(diào)用addSingleton()方法時(shí)已經(jīng)將代理對象通過入?yún)鬟f進(jìn)來。而DefaultSingletonBeanRegistry#getSingleton()的偽代碼如下:
public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {
synchronized (this.singletonObjects) {
Object singletonObject = this.singletonObjects.get(beanName);
if (singletonObject == null) {
... ...
try {
// 這里獲取targetObject的代理對象,實(shí)際會調(diào)用createBean方法
singletonObject = singletonFactory.getObject();
}
... ...
addSingleton(beanName, singletonObject);
}
return singletonObject;
}
}
繼續(xù)向上追溯, AbstractBeanFactory#doGetBean, 其偽代碼如下:
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
// Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, () -> {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
... ...
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
}
return (T) bean;
}
結(jié)合getSingleton和doGetBean方法可知,當(dāng)調(diào)用ObjectFactory的getObject方法時(shí),會觸發(fā)ObjectFactory類的createBean方法執(zhí)行。
至此,我們知道了代理對象的創(chuàng)建是發(fā)生在createBean方法中,因此我們在此處增加條件斷點(diǎn),看看spring在createBean方法中做了哪些操作。
2.3. createBean調(diào)試

設(shè)置好斷點(diǎn)之后,我們重新執(zhí)行程序,一路step into。

圖中最下面的lambda$doGetBean就是我們給createBean設(shè)置斷點(diǎn)的地方。最終程序執(zhí)行到了AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsAfterInitialization。其代碼如下:
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
可以看到這里是遍歷所有的BeanPostProcessor,然后依次執(zhí)行其postProcessAfterInitialization方法。此時(shí)Spring運(yùn)行的相關(guān)變量如下

這里注意一下,程序運(yùn)行到這里,TargetObject對應(yīng)的是原始對象,還沒有被代理。
另外當(dāng)前Spring上下文中包含的BeanPostProcessor中,有一個(gè)AnnotationAwareAspectJAutoProxyCreator。這個(gè)類是個(gè)后置處理器,它和代理對象的創(chuàng)建密不可分。
2.4. AnnotationAwareAspectJAutoProxyCreator調(diào)試
我們先來看看AnnotationAwareAspectJAutoProxyCreator類的繼承結(jié)構(gòu)

可以看到AnnotationAwareAspectJAutoProxyCreator類繼承了BeanPostProcessor和BeanFactoryAware。而BeanFactoryAware接口的postProcessAfterInitialization方法是在父類AbstractAutoProxyCreator中實(shí)現(xiàn)。
下面接著上面的applyBeanPostProcessors方法繼續(xù)調(diào)試。

最終請求鏈路進(jìn)入到ProxyCreatorSupport#createAopProxy方法(接下來的代碼都是創(chuàng)建aop代理對象的核心邏輯),其源碼如下:
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory#createAopProxy
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
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)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
最終調(diào)用JdkDynamicAopProxy#getProxy(java.lang.ClassLoader)方法,其內(nèi)部同步JDK動態(tài)代理,創(chuàng)建代理對象。
Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
至此,我們已經(jīng)清楚的知道Spring是如何創(chuàng)建AOP代理對象。
2.5. 小結(jié)
Spring在創(chuàng)建IOC容器時(shí),通過Spring提供的后置處理器擴(kuò)展點(diǎn),先向容器注冊一個(gè)AnnotationAwareAspectJAutoProxyCreator后置處理器。再通過該后置處理器(其他后置處理器也如此)可以介入bean創(chuàng)建的生命周期,將原生bean通過JDK動態(tài)代理和cglib的方式替換成AOP代理類。
3. @EnableAspectJAutoProxy
上面還有一個(gè)疑問,AnnotationAwareAspectJAutoProxyCreator是怎么注冊到IOC容器中的?答案就是@EnableAspectJAutoProxy。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
可以看到在@EnableAspectJAutoProxy注解中,為引入了(向容器注冊)AspectJAutoProxyRegistrar類。
@Import(AspectJAutoProxyRegistrar.class)
AspectJAutoProxyRegistrar類最終會引入AnnotationAwareAspectJAutoProxyCreator后置處理器,相關(guān)代碼如下:
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
AopConfigUtils
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
注冊AnnotationAwareAspectJAutoProxyCreator的代碼最終是需要創(chuàng)建IOC容器時(shí)來觸發(fā),調(diào)用鏈路圖如下:

3.1. 創(chuàng)建和注冊AnnotationAwareAspectJAutoProxyCreator流程
流程:
1)、傳入配置類(或者配置文件),創(chuàng)建ioc容器
2)、注冊配置類,調(diào)用refresh()刷新容器;
3)、registerBeanPostProcessors(beanFactory);注冊bean的后置處理器來方便攔截bean的創(chuàng)建;

1、先獲取ioc容器已經(jīng)定義了的需要創(chuàng)建對象的所有BeanPostProcessor
2、給容器中加別的BeanPostProcessor
3、優(yōu)先注冊實(shí)現(xiàn)了PriorityOrdered接口的BeanPostProcessor;
4、再給容器中注冊實(shí)現(xiàn)了Ordered接口的BeanPostProcessor;
5、注冊沒實(shí)現(xiàn)優(yōu)先級接口的BeanPostProcessor;
6、注冊BeanPostProcessor,實(shí)際上就是創(chuàng)建BeanPostProcessor對象,保存在容器中;創(chuàng)建internalAutoProxyCreator BeanPostProcessor 【 AnnotationAwareAspectJAutoProxyCreator 】
- 6.1. 創(chuàng)建Bean的實(shí)例
- 6.2. populateBean;給bean的各種屬性賦值
- 6.3. initializeBean:初始化bean;
- 6.3.1. invokeAwareMethods():處理Aware接口的方法回調(diào)
- 6.3.2. applyBeanPostProcessorsBeforeInitialization():應(yīng)用后置處理器的postProcessBeforeInitialization()
- 6.3.3. invokeInitMethods();執(zhí)行自定義的初始化方法
- 6.3.4. applyBeanPostProcessorsAfterInitialization();執(zhí)行后置處理器的postProcessAfterInitialization();
- 6.4. BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)創(chuàng)建成功;--》aspectJAdvisorsBuilder
- 把BeanPostProcessor注冊到BeanFactory中;
beanFactory.addBeanPostProcessor(postProcessor);