Spring AOP原理解析
AOP原理解析
要想使aop生效需要@EnableAspectJAutoProxy支持,我们查看注解内部@Import(AspectJAutoProxyRegistrar.class)
@Import也是讲bean交给spring容器管理的一种方式,常见于第三方bean。 AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar,
ImportBeanDefinitionRegistrar也是一种bean交给spring容器的方式。会由指定的后置处理器调用registerBeanDefinitions方法,直接将bean封装成为
beanDefinition然后注册到容器中,后续由遍历创建bean.
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);
}
}
}
具体这个方法在哪里调用呢?
我们知道配置类解析是由ConfigurationClassPostProcessor来做的,做配置类的解析时会解析@import注解等等,
封装ConfigurationClass,然后解析成为BeanDefinition,然后进行注册。所以在进行BeanDefinition后置处理器注册的时候
会调用这个方法。这个方法具体的作用是创建一个
beanDefinition(org.springframework.aop.config.internalAutoProxyCreator)cls:AspectJAwareAdvisorAutoProxyCreator进行注册:
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;
AspectJAwareAdvisorAutoProxyCreator是属于InstantiationAwareBeanPostProcessor的实现类,所以在进行创建bean创建相关的后置处理器的时候会进行实例化
并对容器的创建进行增强,实例化的步骤这里省略。
后续的步骤就是进行我们自定义创建bean的初始化操作了
我们主要关注aspect类和做增强的类的创建与初始化。在我们创建bean的过程中,会循环遍历已创建的后置处理器
在bean的初始化的方法前后做增强。我们关注aop相关的AspectJAwareAdvisorAutoProxyCreator做的增强
首先是前置:
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
在实例第一个自定义bean的时候,在创建好了bean之后进行bean的初始化方法后置增强的时候会去判断当前bean是否需要进行做代理,会进入shouldSkip方法进行判断, 这个方法会对我们的aspect和advisor进行缓存。在方法findCandidateAdvisors中
会调用this.aspectJAdvisorsBuilder.buildAspectJAdvisors()的方法。这个将@Aspect注解的beanName放到BeanFactoryAspectJAdvisorsBuilder的List aspectBeanNames;
将一个个方法封装成为advisor放到Map<String, List> advisorsCache = new ConcurrentHashMap<>();中
List<String> aspectNames = this.aspectBeanNames;//缓存的apectBean的名字集合
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
//找到当前所有已创建和未创建的bean的name数组
//遍历数组找到@aspect的类
for (String beanName : beanNames) {
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName);
if (beanType == null) {
continue;
}
if (this.advisorFactory.isAspect(beanType)) {
//判断是否属于aspect的类,属于将beanName缓存,然后找到当前类中的所有的advisor,并缓存
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
return advisors;
}
}
}
再看被增强类的初始化:主要是看初始化方法的后置处理:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
如果这个类有advice的话就创建代理类
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
//标识当前类是advisedBean
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;
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
这个方法会为当前bean找到合适的advisor。通过我们定义在pointCut上面的expression来匹配。如果能匹配到advisor的话
同时会添加一个默认的advisor,这个advisor为单例并对所有的bean都匹配,然后对advisor进行排序
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//找到所有的advisor,先从缓存找,找不到去创建
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//为bean找到合适的advisor集合
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//匹配advisor不为空,添加一个默认的advisor到第一位,匹配所有的bean
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对匹配的advisor进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
关于采用何种代理类,如果增强类为接口类型的话就默认此采用jdk的动态代理,其他采用cglib的动态代理方式
@Override
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);
}
}
真正在容器中保存的对象是动态代理的对象,这个当我们在debug获取容器对象的时候能够很清楚的看到其实拿到的是代理对象
=======================
当我们在调用增强的方法的时候,我们以CGLIB动态代理为例,当我们调用我们被增强的方法时实际调用的是
DynamicAdvisedInterceptor.intercept方法首先会拿到一个advisor链
List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
因为通过容器拿到的是代理类,所有不管是非增强方法还是增强方法都会被intercept拦截
,只不过非增强方法获取advisor链拿到的是默认的advisor,这个方法并不会做任何增强。
若执行方法为增强方法,则这个链的顺序为:
0.exposeInvocationInterceptor 这个是默认的advisor
1.afterThrowingAdvice
2.afterReturningAdvice
3.afterAdvice
4.aroundAdvice
5.beforeAdvice
所有的advice的调用是压栈式的,类似于递归调用
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early
//index从-1开始,当最后一个advisor的proceed方法执行完成,index=size-1,开始执行目标方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
每递归一次index+1,取出下一个advisor,然后调用proceed方法
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
具体执行流程图:
@Pointcut("execution(* com.learning.controller.*.*(..))")
public void pointCut(){}
@Before("pointCut()")
public void doBefore(){
System.out.println("OrderAspect doBefore.........");
}
@After("pointCut()")
public void doAfter(){
System.out.println("OrderAspect doAfter............");
}
@AfterReturning("pointCut()")
public void doAfterReturning(){
System.out.println("OrderAspect doAfterReturning......................");
}
@AfterThrowing("pointCut()")
public void doAfterThrowing(){
System.out.println("OrderAspect doAfterThrowing..................");
}
@Around("pointCut()")
public void doAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("OrderAspect doAround..................begin");
pjp.proceed();
System.out.println("OrderAspect doAround..................end");
}
执行结果:
OrderAspect doAround…begin
OrderAspect doBefore…
OrderController execute method…
OrderAspect doAround…end
OrderAspect doAfter…
OrderAspect doAfterReturning…