Spring AOP的实现原理之获取增强器Adivors
来源:互联网 发布:怎么开淘宝网点 编辑:程序博客网 时间:2024/06/05 11:02
在讲解<aop>自定义标签时,提到了AspectJAwareAdvisorAutoProxyCreator的注册,对于AOP的实现基本就靠这个类实现。
AspectJAwareAdvisorAutoProxyCreator的层次结构如图所示,该类实现了BeanPostProcessor与SmartInstantiationAwareBeanPostProcessor这两个接口
ApplicationContext实现的默认行为就是会将所有的单例bean提前进行实例化,即会调用getBean(name),跟踪代码到AbstractAutowireCapableBeanFactory中createBean
此时 resolveBeforeInstantiation(beanName, mbd)就是给实现了SmartInstantiationAwareBeanPostProcessor接口的类的机会去改变bean
AbstractAutowireCapableBeanFactoryprotected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){......try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbd);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}Object beanInstance = doCreateBean(beanName, mbd, args);if (logger.isDebugEnabled()) {logger.debug("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {Object bean = null;if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {// Make sure bean class is actually resolved at this point.if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName);if (bean != null) {bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);}}mbd.beforeInstantiationResolved = (bean != null);}return bean;}如最上面的类层次结构图,此时会调用AbstractAutoProxyCreator中的postProcessBeforeInstantiation以及postProcessAfterInstantiation方法
protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName)throws BeansException {for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName);if (result != null) {return result;}}}return null;}注意shouldSkip(beanClass, beanName),该方法其实已经找到所有的标有@AspectJ类中的增加方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {Object cacheKey = getCacheKey(beanClass, beanName);if (beanName == null || !this.targetSourcedBeans.containsKey(beanName)) {if (this.advisedBeans.containsKey(cacheKey)) {return null;}if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return null;}}// Create proxy here if we have a custom TargetSource.// Suppresses unnecessary default instantiation of the target bean:// The TargetSource will handle target instances in a custom fashion.if (beanName != null) {TargetSource targetSource = getCustomTargetSource(beanClass, beanName);if (targetSource != null) {this.targetSourcedBeans.put(beanName, Boolean.TRUE);Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}}return null;}public boolean postProcessAfterInstantiation(Object bean, String beanName) {return true;}
AspectJAwareAdvisorAutoProxyCreator@Overrideprotected boolean shouldSkip(Class beanClass, String beanName) {// TODO: Consider optimization by caching the list of the aspect namesList<Advisor> candidateAdvisors = findCandidateAdvisors();for (Advisor advisor : candidateAdvisors) {if (advisor instanceof AspectJPointcutAdvisor) {if (((AbstractAspectJAdvice) advisor.getAdvice()).getAspectName().equals(beanName)) {return true;}}}return super.shouldSkip(beanClass, beanName);}
findCadidateAdvisors()即是寻找所有的增加方法,即标有@Before,@After,@AfterReturning,@Around等注解的方法,一个增强方法对应Advisor.
下面来看看findCadidateAdvisors()的逻辑
@Overrideprotected List<Advisor> findCandidateAdvisors() {// 这个是寻找xml配置文件的advisorsList<Advisor> advisors = super.findCandidateAdvisors();// 寻找标有注解的advisors,advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());return advisors;}
如上所示,spring把寻找标有注解的advisor委托给了BeanFactoryAspectJAdvisorsBuilder
public List<Advisor> buildAspectJAdvisors() {List<String> aspectNames = null;synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {....//获取所有注册的beanNameString[] beanNames =BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);for (String beanName : beanNames) {....//判断beanType是否存在AspectJ注解if (this.advisorFactory.isAspect(beanType)) {aspectNames.add(beanName);//AspectMetadata代表标有@AspectJ的类AspectMetadata amd = new AspectMetadata(beanType, beanName);if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {....//获取标记AspectJ注解中的增强方法List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);....}....}this.aspectBeanNames = aspectNames;return advisors;}}....}
重点在this.advisorFactory.getAdvisors(factory)
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();final String aspectName = maaif.getAspectMetadata().getAspectName();...final List<Advisor> advisors = new LinkedList<Advisor>();//getAdvisorMethods()寻找增强方法,即标有注解的方法不过排出了@Poincut//并且是有序的集合,顺序分别是Around, Before, After, AfterReturning, AfterThrowing//这也是5种通知在AOP中的拦截顺序for (Method method : getAdvisorMethods(aspectClass)) {//全部以InstantiationModelAwarePointcutAdvisorImpl返回Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);if (advisor != null) {advisors.add(advisor);}}...return advisors;}
回到文章最开始,AspectJAwareAdvisorAutoProxyCreator实现了BeanPostProcessor接口,那么这个接口的方法在哪儿实现呢?答案在AbstractAutowireCapableBeanFactory类的initializeBean方法中,该方法调用applyBeanPostProcessorsAfterInitialization方法,即是BeanPostProcessor接口方法的调用之处
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {......Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {//BeanPostProcessor接口postProcessBeforeInitialization实现wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {//initMethod方法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()) {//BeanPostProcessor接口postProcessAfterInitialization实现wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.containsKey(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
接下来看看wrapIfNecessary方法,该方法就是创建代理的地方了,匹配切点表达式的增强器就是getAdvicesAndAdvisorsForBean这个方法得来的protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {...// 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;}跟踪getAdvicesAndAdvisorsForBean方法
protected List<Advisor> findEligibleAdvisors(Class beanClass, String beanName) {//该句代码在上面已做了分析List<Advisor> candidateAdvisors = findCandidateAdvisors();//在candidateAdvisors中寻找匹配目标类的增加器List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}跟踪findAdvisorsThatCanApply方法,其逻辑委托给了AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}...boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {...if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}
当前循环的增强器是否匹配目标类是由canApply()方法判断的。放在编码阶段,就是目标类是否满足切点表达式,比如:execution(* com.uestc.test.aop.*.*(..)),即com.uestc.test.aop包下类的任何方法都应进行增强。
跟踪canApply方法,可以看到是通过MethodMatcher.match()方法来匹配的
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 HashSet<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;}
其匹配过程大致是通过提取切入点表达式,根据切入点表达式来判断是否匹配,但是前面分析寻找增强方法时对于标有@Poincut注解的方法排除了,也没有看到切点表达式的提取。
我们来看看getClassFilter()
public ClassFilter getClassFilter() {checkReadyToMatch();return this;}对,切入点表达式的提取就在checkReadyToMacth()方法中
private void checkReadyToMatch() {if (getExpression() == null) {throw new IllegalStateException("Must set property 'expression' before attempting to match");}if (this.pointcutExpression == null) {this.pointcutExpression = buildPointcutExpression();}}buildPointCutExpression()即是提取切入点表达式,返回的类型是PointcutExpressionImpl,简单描述spring的做法就是通过反射来提取,但是spring的做法远比这复杂的多,这里暂不做分析。
由此,我们就找到了匹配目标类的增强器。
- Spring AOP的实现原理之获取增强器Adivors
- spring aop 之增强器处理
- spring AOP的实现原理
- Spring的AOP实现原理
- Spring Aop 的实现原理
- Spring AOP的实现原理
- spring AOP的实现原理
- Spring 的aop实现原理
- Spring的AOP实现原理
- Spring AOP的实现原理
- spring aop的实现原理
- 七.Spring AOP 之增强
- Spring AOP之增强介绍
- Spring AOP之增强(aspectj)
- Spring AOP的实现原理之代理创建
- Spring AOP的实现原理之<aop:aspectj-autoproxy />的解析
- Spring AOP的实现原理之<aop:aspectj-autoproxy />的解析
- spring AOP实现原理
- C++ 指向函数的指针
- linux-/usr存在的意义与内容
- leetcode之Single Number
- Sql分区表的管理:添加,修改,查询分区表中的数据
- linux中使用hbase出现 Failed to start master java.lang.RuntimeException: HMaster Aborted
- Spring AOP的实现原理之获取增强器Adivors
- 黑马程序员-API之【Object】、【System】、【Rutime】、【Math】、【Date】、【Calendar】
- C语言中auto,register,extern,static【转】
- 学习Android之第五个小程序新浪微博样式(Listview的使用)
- C语言 指向函数的指针
- -----------------INSTALL_FAILED_INSUFFICIENT_STORAGE 异常的解决方法
- Codeforces Round #239 (Div. 2) A~D
- hadoop 0.20.2 多文件输出
- Chapter 1 unit 2 of Bootstrap-Bootstrap Scaffolding