https://www.cnblogs.com/wade-luffy/p/6076823.html
對(duì)于指定bean的增強(qiáng)方法的獲取一定是包含兩個(gè)步驟的:
- 獲取所有的增強(qiáng)
- 尋找所有增強(qiáng)中使用于bean的增強(qiáng)并應(yīng)用
那么findCandidateAdvisors與findAdvisorsThatCanApply便是做了這兩件事情。當(dāng)然,如果無(wú)法找到對(duì)便返回DO_NOT_PROXY晦譬,其中DO_NOT_PROXY=null.
protected Object[] getAdvicesAndAdvisorsForBean(Class beanClass, String beanName, TargetSource targetSource)
{
List advisors = findEligibleAdvisors(beanClass, beanName);
if(advisors.isEmpty())
return DO_NOT_PROXY;
else
return advisors.toArray();
}
protected List findEligibleAdvisors(Class beanClass, String beanName)
{
//獲取所有的增強(qiáng)器
List candidateAdvisors = findCandidateAdvisors();
//獲取適合beanname的增強(qiáng)器
List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if(!eligibleAdvisors.isEmpty())
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
return eligibleAdvisors;
}
所有增強(qiáng)器的獲取
由于分析的是使用注解進(jìn)行的AOP了罪,所以對(duì)于findCandidateAdvisors的實(shí)現(xiàn)其實(shí)是由AnnotationAwareAspectJAutoProxyCreator類完成的狮暑,我們繼續(xù)跟蹤AnnotationAwareAspectJAutoProxyCreator的findCandidateAdvisors方法艰躺。
protected List findCandidateAdvisors() {
//當(dāng)使用注解方式配置AOP的時(shí)候并不是丟棄了對(duì)XML配置的支持侄泽。
//在這里調(diào)用父類方法加載配置文件中的AOP聲明
List advisors = super.findCandidateAdvisors();
//Build Advisors for all AspectJ aspects in the bean factory
advisors.addAll(aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
AnnotationAwareAspectJAutoProxyCreator間接繼承了AbstractAdvisorAutoProxyCreator绍撞,在實(shí)現(xiàn)獲取增強(qiáng)的方法中除了保留父類的獲取配置文件中定義的增強(qiáng)外正勒,同時(shí)添加了獲取Bean的注解增強(qiáng)的功能,那么其實(shí)現(xiàn)正是由this.aspectJAdvisorsBuilder.buildAspectJAdvisors()來(lái)實(shí)現(xiàn)的傻铣。
(1)獲取所有beanName章贞,這一步驟中所有在beanFactory中注冊(cè)的Bean都會(huì)被提取出來(lái)。
(2)遍歷所有beanName非洲,并找出聲明AspectJ注解的類鸭限,進(jìn)行進(jìn)一步的處理就谜。
(3)對(duì)標(biāo)記為AspectJ注解的類進(jìn)行增強(qiáng)器的提取。
(4)將提取結(jié)果加入緩存里覆。
提取Advisor
現(xiàn)在來(lái)看看函數(shù)實(shí)現(xiàn)丧荐,對(duì)Spirng中所有的類進(jìn)行分析,提取Advisor喧枷。
public List buildAspectJAdvisors()
{
List aspectNames = null;
synchronized(this){
aspectNames = aspectBeanNames;
if(aspectNames == null)
{
List advisors = new LinkedList();
aspectNames = new LinkedList();
//獲取所有的beanName
String beanNames[] = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(beanFactory, java/lang/Object, true, false);
//循環(huán)所有的beanName找出對(duì)應(yīng)的增強(qiáng)方法
for(String beanName : beanNames)
{
//不合法的bean則略過(guò)虹统,由子類定義規(guī)則,默認(rèn)返回true
if(!isEligibleBean(beanName))
continue;
//獲取對(duì)應(yīng)的bean的類型
Class beanType = beanFactory.getType(beanName);
//如果存在Aspect注解
if(beanType == null || !advisorFactory.isAspect(beanType))
continue;
aspectNames.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
MetadataAwareAspectInstanceFactory factory;
if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON)
{
factory = new BeanFactoryAspectInstanceFactory(beanFactory, beanName);
//解析標(biāo)記AspectJ注解中的增強(qiáng)方法
List classAdvisors = advisorFactory.getAdvisors(factory);
if(beanFactory.isSingleton(beanName))
advisorsCache.put(beanName, classAdvisors);
else
aspectFactoryCache.put(beanName, factory);
advisors.addAll(classAdvisors);
continue;
}
if(beanFactory.isSingleton(beanName))
throw new IllegalArgumentException((
new StringBuilder()).append("Bean with name '")
.append(beanName)
.append("' is a singleton, but aspect instantiation model is not singleton")
.toString());
factory = new PrototypeAspectInstanceFactory(beanFactory, beanName);
aspectFactoryCache.put(beanName, factory);
advisors.addAll(advisorFactory.getAdvisors(factory));
}
aspectBeanNames = aspectNames;
return advisors;
}
至此隧甚,已經(jīng)完成了Advisor的提取车荔。
切點(diǎn)信息的獲取
在上面的步驟中最為重要也最為繁雜的就是增強(qiáng)器的獲取,而這一切功能委托給了getAdvisors方法去實(shí)現(xiàn)(this.advisorFactory.getAdvisors(factory))戚扳。
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {
//獲取標(biāo)記為AspectJ的類
final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();
//獲取標(biāo)記為AspectJ的name
final String aspectName = maaif.getAspectMetadata().getAspectName();
//驗(yàn)證
validate(aspectClass);
final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(maaif);
final List<Advisor> advisors = new LinkedList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
//如果尋找的增強(qiáng)器不為空而且又配置了增強(qiáng)延遲初始化那么需要在首位加入同步實(shí)例化增強(qiáng)器
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
//對(duì)DeclareParents注解的獲取
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
函數(shù)中首先完成了增強(qiáng)器的獲取忧便,包括獲取注解以及根據(jù)注解生成增強(qiáng)的步驟,然后考慮到在配置中可能會(huì)將增強(qiáng)配置成延遲初始化帽借,那么需要在首位加入同步實(shí)例化增強(qiáng)器以保證增強(qiáng)使用之前的實(shí)例化珠增,最后是對(duì)DeclareParents注解的獲取。
普通增強(qiáng)器的獲取邏輯通過(guò)getAdvisor方法實(shí)現(xiàn)砍艾,實(shí)現(xiàn)步驟包括對(duì)切點(diǎn)的注解的獲取及根據(jù)注解信息生成增強(qiáng)蒂教。
(1)切點(diǎn)信息的獲取。所謂獲取切點(diǎn)信息就是指定注解的表達(dá)式信息的獲取脆荷,如@Before("test()")
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName)
{
validate(aif.getAspectMetadata().getAspectClass());
//切點(diǎn)信息的獲取
AspectJExpressionPointcut ajexp = getPointcut(candidateAdviceMethod, aif.getAspectMetadata().getAspectClass());
if(ajexp == null)
return null;
else
//根據(jù)切點(diǎn)信息生成增強(qiáng)器
return new InstantiationModelAwarePointcutAdvisorImpl(this, ajexp, aif, candidateAdviceMethod, declarationOrderInAspect, aspectName);
}
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//獲取方法上的注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if (aspectJAnnotation == null) {
return null;
}
//使用AspectJExpressionPointcut實(shí)例封裝獲取的信息
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class[0]);
//提取得到的注解中的表達(dá)式如:@Pointcut("execution(* *.*test*(..))")中的execution(* *.*test*(..))
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
return ajexp;
}
protected static AspectJAnnotation findAspectJAnnotationOnMethod(Method method) {
//設(shè)置敏感的注解類
Class<? extends Annotation>[] classesToLookFor = new Class[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<? extends Annotation> c : classesToLookFor) {
AspectJAnnotation foundAnnotation = findAnnotation(method, c);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
//獲取指定方法上的注解并使用AspectJAnnotation封裝
private static <A extends Annotation> AspectJAnnotation<A> findAnnotation(Method method, Class<A> toLookFor) {
A result = AnnotationUtils.findAnnotation(method, toLookFor);
if (result != null) {
return new AspectJAnnotation<A>(result);
}
else {
return null;
}
}
(2)根據(jù)切點(diǎn)信息生成增強(qiáng)凝垛。所有的增強(qiáng)都有Advisor實(shí)現(xiàn)類InstantiationModelAwarePontcutAdvisorImpl統(tǒng)一封裝。
public InstantiationModelAwarePointcutAdvisorImpl(AspectJAdvisorFactory af, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, Method method, int declarationOrderInAspect, String aspectName) {
this.declaredPointcut = ajexp;
this.method = method;
this.atAspectJAdvisorFactory = af;
this.aspectInstanceFactory = aif;
this.declarationOrder = declarationOrderInAspect;
this.aspectName = aspectName;
if (aif.getAspectMetadata().isLazilyInstantiated()) {
Pointcut preInstantiationPointcut =
Pointcuts.union(aif.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
this.pointcut = new PerTargetInstantiationModelPointcut(this.declaredPointcut, preInstantiationPointcut, aif);
this.lazy = true;
}
else {
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
this.pointcut = declaredPointcut;
this.lazy = false;
}
}
封裝過(guò)程只是簡(jiǎn)單地將信息封裝在類的實(shí)例中蜓谋,所有的信息單純地復(fù)制梦皮。在實(shí)例初始化的過(guò)程中還完成了對(duì)于增強(qiáng)器的初始化。因?yàn)椴煌脑鰪?qiáng)所體現(xiàn)的邏輯是不同的桃焕,比如@Before(“test()”)與After(“test()”)標(biāo)簽的不同就是增強(qiáng)器增強(qiáng)的位置不同剑肯,所以就需要不同的增強(qiáng)器來(lái)完成不同的邏輯,而根據(jù)注解中的信息初始化對(duì)應(yīng)的增強(qiáng)器就是在instantiateAdvice函數(shù)中實(shí)現(xiàn)的覆旭。
private Advice instantiateAdvice(AspectJExpressionPointcut pcut)
{
return atAspectJAdvisorFactory.getAdvice(method, pcut, aspectInstanceFactory, declarationOrder, aspectName);
}
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut ajexp,
MetadataAwareAspectInstanceFactory aif, int declarationOrderInAspect, String aspectName)
{
Class candidateAspectClass = aif.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
AbstractAspectJAdvisorFactory.AspectJAnnotation aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
if(aspectJAnnotation == null)
return null;
if(!isAspect(candidateAspectClass))
throw new AopConfigException(
(new StringBuilder())
.append("Advice must be declared inside an aspect type: Offending method '")
.append(candidateAdviceMethod)
.append("' in class [")
.append(candidateAspectClass.getName())
.append("]").toString());
if(logger.isDebugEnabled())
logger.debug((new StringBuilder()).append("Found AspectJ method: ").append(candidateAdviceMethod).toString());
AbstractAspectJAdvice springAdvice;
switch(SwitchMap.org.springframework.aop.aspectj.annotation.AbstractAspectJAdvisorFactory.AspectJAnnotationType
[aspectJAnnotation.getAnnotationType().ordinal()])
{
case 1: // '\001'
springAdvice = new AspectJMethodBeforeAdvice(candidateAdviceMethod, ajexp, aif);
break;
case 2: // '\002'
springAdvice = new AspectJAfterAdvice(candidateAdviceMethod, ajexp, aif);
break;
case 3: // '\003'
springAdvice = new AspectJAfterReturningAdvice(candidateAdviceMethod, ajexp, aif);
AfterReturning afterReturningAnnotation = (AfterReturning)aspectJAnnotation.getAnnotation();
if(StringUtils.hasText(afterReturningAnnotation.returning()))
springAdvice.setReturningName(afterReturningAnnotation.returning());
break;
case 4: // '\004'
springAdvice = new AspectJAfterThrowingAdvice(candidateAdviceMethod, ajexp, aif);
AfterThrowing afterThrowingAnnotation = (AfterThrowing)aspectJAnnotation.getAnnotation();
if(StringUtils.hasText(afterThrowingAnnotation.throwing()))
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
break;
case 5: // '\005'
springAdvice = new AspectJAroundAdvice(candidateAdviceMethod, ajexp, aif);
break;
case 6: // '\006'
if(logger.isDebugEnabled())
logger.debug(
(new StringBuilder()).append("Processing pointcut '")
.append(candidateAdviceMethod.getName())
.append("'").toString());
return null;
default:
throw new UnsupportedOperationException(
(new StringBuilder()).append("Unsupported advice type on method ")
.append(candidateAdviceMethod).toString());
}
springAdvice.setAspectName(aspectName);
springAdvice.setDeclarationOrder(declarationOrderInAspect);
String argNames[] = parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if(argNames != null)
springAdvice.setArgumentNamesFromStringArray(argNames);
springAdvice.calculateArgumentBindings();
return springAdvice;
}
}
從函數(shù)中可以看到退子,Spring會(huì)根據(jù)不同的注解生成不同的增強(qiáng)器岖妄,例如AtBefore會(huì)對(duì)應(yīng)AspectJMethodBeforeAdvice型将。
增加同步實(shí)例化增強(qiáng)器
如果尋找的增強(qiáng)器不為空而且又配置了增強(qiáng)延遲初始化,那么就需要在首位加入同步實(shí)例化增強(qiáng)器荐虐。
protected static class SyntheticInstantiationAdvisor extends DefaultPointcutAdvisor {
public SyntheticInstantiationAdvisor(final MetadataAwareAspectInstanceFactory aif) {
super(aif.getAspectMetadata().getPerClausePointcut(), new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] args, Object target) {
// Simply instantiate the aspect
aif.getAspectInstance();
}
});
}
}
獲取DeclareParents注解
DeclareParents主要用于引介增強(qiáng)的注解形式的實(shí)現(xiàn)七兜,而其實(shí)現(xiàn)方式馭普通增強(qiáng)很類似,只不過(guò)使用DeclareParentsAdvisor對(duì)功能進(jìn)行封裝福扬。
引介是一種特殊的增強(qiáng)腕铸,它為類添加一些屬性和方法惜犀。這樣,即使一個(gè)業(yè)務(wù)類原本沒(méi)有實(shí)現(xiàn)某個(gè)接口狠裹,通過(guò)引介功能虽界,可以動(dòng)態(tài)的未該業(yè)務(wù)類添加接口的實(shí)現(xiàn)邏輯,讓業(yè)務(wù)類成為這個(gè)接口的實(shí)現(xiàn)類涛菠。
private Advisor getDeclareParentsAdvisor(Field introductionField)
{
DeclareParents declareParents = (DeclareParents)introductionField.getAnnotation(org/aspectj/lang/annotation/DeclareParents);
if(declareParents == null)
return null;
if("org/aspectj/lang/annotation/DeclareParents".equals(declareParents.defaultImpl()))
throw new IllegalStateException("defaultImpl must be set on DeclareParents");
else
return new DeclareParentsAdvisor(introductionField.getType(), declareParents.value(), declareParents.defaultImpl());
}
至此已經(jīng)完成了所有增強(qiáng)器的解析莉御,但是對(duì)于所有增強(qiáng)器來(lái)講,并不一定都適用于當(dāng)前的Bean俗冻,還要挑取除適合的增強(qiáng)器礁叔,也就是滿足我們配置的通配符的增強(qiáng)器。具體的實(shí)現(xiàn)在findAdvisorsThatCanApply中迄薄。
獲取合適的增強(qiáng)器
findAdvisorsThatCanApply函數(shù)的主要功能是尋找所有增強(qiáng)器中適用于當(dāng)前class的增強(qiáng)器琅关。對(duì)于真是的匹配在canApply中實(shí)現(xiàn)。
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();
//首先處理引介增強(qiáng)
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
if (candidate instanceof IntroductionAdvisor) {
continue;
}
//對(duì)于普通bean的處理
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class> classes = new LinkedHashSet<Class>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = clazz.getMethods();
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}