Spring环境下AOP运行原理
前面文章已经分析了
SpringAop
原生的运行原理,本节将分析使用频率最高场景:
Spring
环境下的
AOP
运行原理。本文会涉及到
Spring
启动期间注入
Bean
的流程,默认你已经非常熟悉了,本文不再详细赘述相关流程。
在
SpingBoot
项目中使用
AOP
一般会做如下操作:
-
主启动类上添加
@EnableAspectJAutoProxy
注解开启
SpringAop
功能 -
自定义切面并注入到
Spring
中即可
@SpringBootApplication
@EnableAspectJAutoProxy
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
@Aspect
@Component
public class TestAspect {
@Pointcut(value = "execution(* com.ssm.test.aop.ATMService.withdrawMoney())")
public void pointcut() {}
@Before(value = "pointcut()")
public void before() {
System.out.println("TestAspect.before.....");
}
@After(value = "pointcut()")
public void after() {
System.out.println("TestAspect.after.....");
}
}
@Service
public class ATMService implements BankService {
@Override
public void withdrawMoney() {
System.out.println("ATMService : 取钱成功");
}
}
如上代码所示是一个简单的
AOP
增强案例,本节就基于这个案例分析
Spring
环境下
AOP
的运行原理。
原理分析
@EnableAspectJAutoProxy
@EnableAspectJAutoProxy
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
boolean proxyTargetClass() default false;
boolean exposeProxy() default false;
}
首先分析下在主启动类上添加的的
@EnableAspectJAutoProxy
注解 , 该注解主要是用于配置
proxyTargetClass、exposeProxy
属性,这个两个属性在之前的文章也分析过了,此处不再赘述。如上图源码所示该注解还有有一个非常关键的作用 :
@Import(AspectJAutoProxyRegistrar.class)
, 了解过
Spring
原理可以知道这边
@Import
注解是用来注入
AspectJAutoProxyRegistrar
这个
Bean
的.
AspectJAutoProxyRegistrar
AspectJAutoProxyRegistrar
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);
}
}
}
}
如上图源码所示,
AspectJAutoProxyRegistrar
将
BeanDefinitionRegistry
作为参数将主要逻辑都委托给了
AopConfigUtils
这个工具类。
BeanDefinitionRegistry
接口并不陌生,主要提供
注册、删除、获取Bean
的功能,所以可以大致判断出
AopConfigUtils
在这边主要是注入了某个
Bean
:
AopConfigUtils
AopConfigUtils
public abstract class AopConfigUtils {
//The bean name of the internally managed auto-proxy creator.
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator";
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);
}
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
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);
//将当前要注入的Bean的优先级设置为最高
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE);
}
}
public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) {
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
definition.getPropertyValues().add("exposeProxy", Boolean.TRUE);
}
}
.....
}
结合上图源码可知
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
这行代码实际上是手动向
Spring
注入了
beanName
为
org.springframework.aop.config.internalAutoProxyCreator
,
Bean类型为 : AnnotationAwareAspectJAutoProxyCreator.class
的
Bean
. 有个细节需要注意:
registerOrEscalateApcAsRequired()
方法注入
Bean
时会为该
Bean
设置
order
属性,将
Bean
的优先级调整为最高级别,这样做的目的是可以优先注入该
Bean
, 但优先注入这个
Bean
具体有何意义此处先
Mark
一下。
forceAutoProxyCreatorToUseClassProxying()、forceAutoProxyCreatorToExposeProxy()
两个方法实际上是为上面注入的
AnnotationAwareAspectJAutoProxyCreator
这个Bean设置
proxyTargetClass、exposeProxy
属性值。虽然
@EnableAspectJAutoProxy
注解中这两个属性值默认值为
false
, 但是底层源码却直接将属性值置为了
true
, 从而可以知道
SpringBoot
中使用
SpringAop
默认会使用强制使用
CGLIB
代理,并且会将当前的代理对象暴露在当前线程中,可以直接使用
AopContext
获取到当前代理对象。
综上所述可以总结出: 主启动类上添加
@EnableAspectJAutoProxy
这个注解可以向
Spring
中注入
AnnotationAwareAspectJAutoProxyCreator
这个
Bean
, 具体它是用来干嘛的此处先不表,下面会详细分析它。
AnnotationAwareAspectJAutoProxyCreator
AnnotationAwareAspectJAutoProxyCreator
如上图所示是
AnnotationAwareAspectJAutoProxyCreator
的
UML
图,由于涉及的比较多所以分析时只会贴出关键代码。上图可以很清楚的看出
AnnotationAwareAspectJAutoProxyCreator
实现了
BeanPostProcessor、InstantiationAwareBeanPostProcessor
接口,所以本质上是一个
BeanPostProcessor
. 对
Spring
了解的同学应该都知道
Spring
在启动期间注入
Bean
时,会使用
IOC
中的
BeanPostProcessor
类型的
Bean
对当前
Bean
的注入做增强处理(相当于是一个埋点处理), 我们简单贴个代码回顾一下 :
public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFactory
implements AutowireCapableBeanFactory {
......
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args) {
try {
//Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
}
catch (Throwable ex) {
throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,
"BeanPostProcessor before instantiation of bean failed", ex);
}
try {
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {
throw ex;
}
catch (Throwable ex) {
throw new BeanCreationException("", ex);
}
}
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
......
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//调用BeanPostProcessor接口中的postProcessBeforeInitialization方法
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException("Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
//调用BeanPostProcessor接口中的postProcessAfterInitialization方法
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//调用BeanPostProcessor接口InstantiationAwareBeanPostProcessor接口中的postProcessBeforeInstantiation方法
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//调用BeanPostProcessor接口中的postProcessAfterInitialization方法
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
......
}
如上图所示是
Spring
遍历注入一个
Bean
时会调用到
AbstractAutowireCapableBeanFactory#createBean()
方法,在这个方法中有这样一行代码 :
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
这行代码上有一行非常重要的注释 :
给BeanPostProcessor一个机会返回代理实例而不是目标实例
。 仔细观察
resolveBeforeInstantiation()
方法逻辑可以看到它主要是遍历调用
IOC
中所有的
BeanPostProcessor
的
postProcessBeforeInstantiation
方法(该方法属于
InstantiationAwareBeanPostProcessor
)和
postProcessAfterInitialization
方法(该方法属于
BeanPostProcessor
).
createBean
还会委托到
AbstractAutowireCapableBeanFactory#initializeBean()
方法 :
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
......
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
这个方法会在执行
Spring
初始化方法
afterPropertiesSet
前后分别遍历调用
IOC
中所有
BeanPostProcessor
的
postProcessBeforeInitialization
和
postProcessAfterInitialization
方法。
根据上面
AnnotationAwareAspectJAutoProxyCreator
UML图可知它实现了
BeanPostProccesor和InstantiationAwareBeanPostProcessor
接口,所以我们重点关注一下它和
BeanPostProcessor
有关的接口实现 ,这些逻辑在
AnnotationAwareAspectJAutoProxyCreator
的父类
AbstractAutoProxyCreator
中 :
AbstractAutoProxyCreator
AbstractAutoProxyCreator
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
//保存那些有指定TargetSource的Bean的名称
private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
//保存需要被AOP拦截的Bean的名称与它的代理对象Class类型的映射关系
private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
//保存Bean是否需要被AOP拦截,如果需要拦截value为true,否则为false
private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
//该方法是InstantiationAwareBeanPostProcessor接口中的
//根据上面的分析可知该方法会在Spring注入每个Bean的时候都执行
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//这个if用于判断是否已经处理过当前Bean
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//到这个if说明当前的Bean还没被处理过
//isInfrastructureClass方法首先会判断当前Bean是否是一个切面
//重点是shouldSkip方法,该方法第一次调用是会找到当前IOC中所有的切面,然后遍历切面判断当前的Bean是否可以被切点拦截
//以本案例中注入ATMService为例,它不是切面但是需要被AOP拦截,所以这个if为false
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
//获取当前Bean对应的TargetSource实例,由于案例中没有提供ATMService的TargetSource
//所以会这个方法会返回null结束
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
//如果有指定TargetSource则会调用createProxy方法,该方法会使用之前分析过的ProxyFacoty生成代理对象并返回
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) {
return true;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
//该方法是实现的`BeanPostProcessor`接口中的
//该方法会在Spring注入Bean期间执行afterPropertiesSet方法后执行
//这个方法将逻辑委托给了wrapIfNecessary方法
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果targetSourcedBeans包含当前的beanName,说明上面的postProcessBeforeInstantiation方法已经处理过这个Bean了,此处就不需要再处理
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
//如果当前Bean属于Advisor类型则也不需要处理
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
//如果当前Bean是切面或者不需要生成代理对象则直接返回
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//到这一步就说明当前Bean有被切面拦截到所以需要生成当前Bean的代理对象以便实现AOP增强
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//生成当前Bean的代理对象
//使用的是之前分析过的ProxyFactory方式生成了代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
......
}
流程总结
SpringBoot
集成
SpringAop
后会注入
AnnotationAwareAspectJAutoProxyCreator
这个
Bean
, 它是一个
BeanPostProcessor
类型.
Spring
在启动期间遍历注入
Bean
时会遍历调用
IOC
中所有
BeanPostProcessor
类型的
postProcessBeforeInitialization、postProcessAfterInitialization
方法。
AnnotationAwareAspectJAutoProxyCreator
也属于
BeanPostProcessor
,所以
Spring
注入每个
Bean
时也会调用到它的这个两个方法,方法是在它的父类
AbstractAutoProxyCreator
中实现的。
AbstractAutoProxyCreator
中的这两个方法会判断当前
Spring
正在注入的这个
Bean
是否需要被
IOC
中的切面拦截,如果不需要则直接返回不做任何处理,否则会调用它的
createProxy
方法使用之前文章分析过的
ProxyFactory
方式生成当前
Bean
的代理对象并返回,之后的逻辑就和之前文章分析过的代理过程一样了。