---
title: Spring源码系列-第6章-AOP的后置处理器和代理对象的创建
tags:
- Spring源码
categories:
- Spring
- 源码V1
keywords: Spring,框架,spring源码
description: AOP源码
cover: 'https://npm.elemecdn.com/lql_static@latest/logo/spring.png'
abbrlink: 598f6b0d
date: 2022-03-19 12:01:02
---
# 第6章-AOP的后置处理器和代理对象的创建
## 测试类
### MainConfig
```java
@ComponentScan("cn.imlql.spring")
@Configuration
public class MainConfig {
public MainConfig(){
System.out.println("MainConfig...创建了....");
}
}
```
### AopOpenConfig
```java
@EnableAspectJAutoProxy //开启自动代理
@Configuration
public class AopOpenConfig {
}
```
### LogAspect
```java
/**
*
* 正常:前置通知===目标方法===返回通知===后置通知
* 异常: 前置通知===目标方法===异常通知===后置通知
* try{
* 前置通知
* 目标方法的执行
* 返回通知
* }catch(){
* 异常通知
* }finally{
* 后置通知
* }
*
*
*/
@Component //切面也是容器中的组件
@Aspect //说明这是切面
public class LogAspect {
public LogAspect(){
System.out.println("LogAspect...");
}
//前置通知 增强方法/增强器
@Before("execution(* cn.imlql.spring.aop.HelloService.sayHello(..))")
public void logStart(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("logStart()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
//返回通知
@AfterReturning(value = "execution(* cn.imlql.spring.aop.HelloService.sayHello(..))",returning = "result")
public void logReturn(JoinPoint joinPoint,Object result){
String name = joinPoint.getSignature().getName();
System.out.println("logReturn()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【result: "+result+"】");
}
//后置通知
@After("execution(* cn.imlql.spring.aop.HelloService.sayHello(..))")
public void logEnd(JoinPoint joinPoint){
String name = joinPoint.getSignature().getName();
System.out.println("logEnd()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】");
}
//异常
@AfterThrowing(value = "execution(* cn.imlql.spring.aop.HelloService.sayHello(..))",throwing = "e")
public void logError(JoinPoint joinPoint,Exception e){
String name = joinPoint.getSignature().getName();
System.out.println("logError()==>"+name+"....【args: "+ Arrays.asList(joinPoint.getArgs()) +"】【exception: "+e+"】");
}
}
```
### HelloService
```java
@Component //切面存在的化就会返回代理对象
public class HelloService {
public HelloService(){
System.out.println("....");
}
public String sayHello(String name){
String result = "你好:"+name;
System.out.println(result);
int length = name.length();
return result + "---" + length;
}
}
```
### AnnotationMainTest
```java
package cn.imlql.spring;
import cn.imlql.spring.aop.HelloService;
import cn.imlql.spring.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* 注解版Spring的用法
*/
public class AnnotationMainTest {
public static void main(String[] args) {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
//AOP,原理测试
HelloService helloService = applicationContext.getBean(HelloService.class);
helloService.sayHello("zhangsan");
}
}
```
## 如何分析Spring的一个新功能
对于一个Spring的新功能我们应该按照下面的思路分析:这个功能加入哪些组件?这些组件在生命周期期间做了什么?
1. 比如我们分析AOP
1. 分析AOP给容器添加了哪些组件,分析方法如下
1. **第一种方法:**之前讲过的给AbstractBeanDefinition三个构造器打断点,因为绝大多数组件都是要先经过Bean定义信息的。但也不排除Spring直接new组件注册进去,不经过AbstractBeanDefinition(很少很少)。所以此时再给容器刷新refresh()方法的最后一步finishRefresh()打个断点,看容器里此时有哪些组件即可。
2. **第二种方法**:Spring每开启一个功能,要么写配置要么写注解。Spring就要解析这些注解或者配置,Spring里面会有很多@EnableXXX这样的注解,顾名思义,就是开启什么什么功能。分析这种注解即可@EnableXXX,一般来说新功能大概率都是通过后置处理器做的,@EnableXXX肯定也是引入了新的后置处理器。
2. 这些组件在生命周期期间做了什么事。
## 分析@EnableXXX找到负责AOP功能的后置处理器
### @EnableAspectJAutoProxy
```java
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class) //最核心的就是这个@Import了,导入了什么组件
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}
```
#### AspectJAutoProxyRegistrar#registerBeanDefinitions()
```java
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册切面的基于注解的自动代理创建器
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry); //pos_1 在这里打个断点分析一下
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}
```
### Debug调用栈
### ImportBeanDefinitionRegistrar
```java
default void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry,
BeanNameGenerator importBeanNameGenerator) {
registerBeanDefinitions(importingClassMetadata, registry);
}
```
最后就是这样的一个调用实现类
### AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary注册切面的基于注解的自动代理创建器
pos_1 Debug进去是下面的方法
```java
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
```
主要的就是注册了这个AnnotationAwareAspectJAutoProxyCreator组件
### AnnotationAwareAspectJAutoProxyCreator后置处理器
我们发现这就是一个后置处理器,印证了我们之前说过的几乎所有功能增强或功能附加都是由后置处理器来完成
## AnnotationAwareAspectJAutoProxyCreator在生命周期期间做了什么事?
### 怎么分析?
1. 给getBean设置一个条件断点,条件就是BeanName==AnnotationAwareAspectJAutoProxyCreator的时候
2. 给AnnotationAwareAspectJAutoProxyCreator重写的父类的所有方法打上断点,因为它的最顶层接口是BeanPostProcessor 。最终肯定会一层一层往下调实现类实现的方法,大概率会调到AnnotationAwareAspectJAutoProxyCreator重写的方法。当然也不是绝对的,如果debug的时候发现没有停留,那就可以把所有方法都打上断点。或者你看方法名猜一下。
3. 我们这里是两个都做了
### 负责AOP功能的后置处理器第一次运行准备好数据
#### Debug调用栈-调用AnnotationAwareAspectJAutoProxyCreator的initBeanFactory()方法初始化AnnotationAwareAspectJAutoProxyCreator相关属性
##### 作用
1. 由于它是后置处理器所以肯定是在refresh方法里的registerBeanPostProcessors这一步开始干活的
2. 果然是从getBean调用到了我们的重写方法断点处,也就验证了我们上面说怎么分析。绿色包含的前面已经讲过,不再赘述。
3. 也确实是AnnotationAwareAspectJAutoProxyCreator,走到这里说明前面已经创建出了AnnotationAwareAspectJAutoProxyCreator对象(前面怎么创建的,getbean的流程之前已经讲的很清楚了),后面只是对AnnotationAwareAspectJAutoProxyCreator进行初始化
##### AbstractAutowireCapableBeanFactory#initializeBean()进行初始化
注意此时这个参数bean就是AnnotationAwareAspectJAutoProxyCreator对象,往后走的过程中不要忘记
```java
protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction