spring aop源碼分析
前言:
正常流程
前置通知 --> 業務 --> 後置通知
異常流程:
前置通知 --> 業務 --> 後置通知 -> 異常通知
重點
看aop源碼之前必須先分析源碼的流程是怎麼樣的。
-
aop如何加載到spring容器
他又兩種方式啓動:
第一種
xml是一種方式–>>>> 他是如何解析xml —(看到dubbo的源碼就知道 通過擴展spring提供自定義接口NamespaceHandler 重寫init方法)
第二中方式
annotaiton的方式 @EnableAspectJAutoProxy --> @Import(AspectJAutoProxyRegistrar.class) #registerBeanDefinitions 方法也是spring提供的擴展接口。 -
aop是如何攔截bean。
流程分析:
-
將bean導入spring容器AspectJAutoProxyRegistrar->ImportBeanDefinitionRegistrar#registerBeanDefinitions
-
將bean註冊到spring容器 AnnotationAwareAspectJAutoProxyCreator className: org.springframework.aop.config.internalAutoProxyCreator class: 根據spring提供的規範構建spring bean RootBeanDefinition
-
上面構建 AnnotationAwareAspectJAutoProxyCreator 這個bean 然後這個bean實現InstantiationAwareBeanPostProcessor接口
該接口實現BeanPostProcessor接口 BeanPostProcessor是spring提供的擴展接口 在bean實例的時候回調 --》postProcessAfterInitialization -
然後就會找所有的Advisor
1、 第一步: 先找父類時候有實現Advisor的接口。
2、 第二步: 然後找到所有類上面註解標註爲@Aspect, 然後解析該類標註Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class
org.springframework.aop.config.AopNamespaceHandler
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
// 第一步: 註冊解析bean
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
// 第二步: aspectj-autoproxy AspectJAutoProxyBeanDefinitionParser
registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
// Only in 2.0 XSD: moved to context namespace as of 2.1
registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
org.springframework.aop.config.AspectJAutoProxyBeanDefinitionParser
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 看名字應該註冊什麼東西... 繼續分析
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
org.springframework.aop.config.AopNamespaceUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(
ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(
parserContext.getRegistry(), parserContext.extractSource(sourceElement));
// 對於proxy-target-class 已經 expose-proxy屬性的處理
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
// 註冊組件並通知,便於監聽器做進一步處理
registerComponentIfNecessary(beanDefinition, parserContext);
}
總結: 看完上面這個方法主要乾了一下幾件事情
- 註冊與升級
- 屬性的處理
- 通知
下面開始重點分析對以上三件事情做詳細分析
註冊於與升級
org.springframework.aop.config.AopConfigUtils#registerAspectJAnnotationAutoProxyCreatorIfNecessary(org.springframework.beans.factory.support.BeanDefinitionRegistry, java.lang.Object)
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 從命名的角度推測。註冊或者升級aspectJS做爲必須的。
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
org.springframework.aop.config.AopConfigUtils#registerOrEscalateApcAsRequired
/**
參數分析
cls 需要註冊的class
registry: bean容器的註冊中心
source : xml解析完的 the source object to store
*/
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
//org.springframework.aop.config.internalAutoProxyCreator
// 第一步: 判斷容器中是否有該類、
// Check if this registry contains a bean definition with the given name.
// 根據上面的註釋可以說明 通過beanName判斷該容器中是否存在該bean的實例對象。
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 獲取實例對象
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 這個判斷說明了兩個問題
// 容器中存在且與當前bean不一致的情況
// 判斷先使用哪一個的問題
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 比較優先級 findPriorityForClass 繼續跟蹤這部分源碼發現他採用了List作爲容器,並排序。所有
//返回下標
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;
}
屬性的處理
org.springframework.aop.config.AopNamespaceUtils#useClassProxyingIfNecessary
// proxy-target-calss 以及 expose-proxy屬性
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, @Nullable Element sourceElement) {
if (sourceElement != null) {
// proxy-target-calss
boolean proxyTargetClass = Boolean.parseBoolean(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));
if (proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
// expose-proxy
boolean exposeProxy = Boolean.parseBoolean(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));
if (exposeProxy) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
org.springframework.aop.config.AopConfigUtils#forceAutoProxyCreatorToUseClassProxying
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);
}
}
org.springframework.aop.config.AopConfigUtils#forceAutoProxyCreatorToExposeProxy
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);
}
}
總結一下: 代理主要分爲以下幾種代理
- CGLIB
- JDK
-系統是怎麼選擇是JDK代理還是CGLIB代理呢?
JDK 針對的是interface
CGLIB 針對的是 Class.
proxy-target-class 他爲什麼出現。出現的目的是什麼?
自動適配
expose-proxy:
目標對象內部無法實現調用。
AopContext.currentProxy()獲取到當前類對象
通知
org.springframework.aop.config.AopNamespaceUtils#registerComponentIfNecessary
private static void registerComponentIfNecessary(@Nullable BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));
}
}
org.springframework.beans.factory.xml.ParserContext#registerComponent
public void registerComponent(ComponentDefinition component) {
// 等待派發、直接觸發。
CompositeComponentDefinition containingComponent = getContainingComponent();
if (containingComponent != null) {
containingComponent.addNestedComponent(component);
}
else {
this.readerContext.fireComponentRegistered(component);
}
}
下面介紹創建Aop代理
這是spring優雅的地方,通過spring的BeanPostProcess接口xxxxx…
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization
/**
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
// 構建 key的規則 className_beanName
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
// 如果他合適被代理,則需要被代理指定的bean
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary
/**
* Wrap the given bean if necessary, i.e. if it is eligible for being proxied.
* @param bean the raw bean instance
* @param beanName the name of the bean
* @param cacheKey the cache key for metadata access
* @return a proxy wrapping the bean, or the raw bean instance as-is
*/
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 如果已經被處理過
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 無需zhen
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;
}
// Create proxy if we have advice.
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;
}
通過上面的代碼我們已經感覺到aop整合spring開始啦
創建代理對象分爲一下兩個方面
- 獲取增強的方法或者增強器
- 根據獲取到增強進行代理
AbstractAutoProxyCreator
- BeanNameAutoProxyCreator
- AbstractAdvisorAutoProxyCreator
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
總結一下: 獲取所有增強以及尋找所有增強中適應於bean的增強並應用.
// next 分析 …
獲取增強器繼續分析
org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator#findCandidateAdvisors
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
org.springframework.aop.aspectj.annotation.BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors
/**
* Look for AspectJ-annotated aspect beans in the current bean factory,
* and return to a list of Spring AOP Advisors representing them.
* <p>Creates a Spring Advisor for each AspectJ advice method.
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
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);
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)) {
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;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisors
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//獲取標記爲AspectJ類
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
// 獲取標記爲AspectJ的name
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
//
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory#getAdvisor
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
if (expressionPointcut == null) {
return null;
}
// 根據切點信息生成增強類的信息
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
}