Spring源码阅读4.1-Aspecjt AOP之获取Adivsor

来源:互联网 发布:mac单机游戏推荐 编辑:程序博客网 时间:2024/06/06 20:20

我们来看下AOP,不多说,直接从AspectJAutoProxyBeanDefinitionParser说起(注:对不同标签有不同处理器进行解析,而"aspectj-autoproxy"的解析器即为AspectJAutoProxyBeanDefinitionParser)。

@Overridepublic BeanDefinition parse(Element element, ParserContext parserContext) {AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);extendBeanDefinition(element, parserContext);return null;}
parse方法首先去注册AnnotationAwareAspectJAutoProxyCreator类,然后在对element进行解析扩展。
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);registerComponentIfNecessary(beanDefinition, parserContext);}

我们可以看到上述方法获得了BeanDefinition定义,进一步看下细节:

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);}
这里我们看到了AnnotationAwareAspectJAutoProxyCreator.class这个类。
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, 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);beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);return beanDefinition;}

初次启动,第一个if为false,直接去为AnnotationAwareAspectJAutoProxyCreator创建BeanDefinition,以"org.springframework.aop.config.internalAutoProxyCreator"为键值注册。
回到上面的方法,我们看下useClassProxyingIfNecessary
private static void useClassProxyingIfNecessary(BeanDefinitionRegistry registry, Element sourceElement) {if (sourceElement != null) {boolean proxyTargetClass = Boolean.valueOf(sourceElement.getAttribute(PROXY_TARGET_CLASS_ATTRIBUTE));if (proxyTargetClass) {
//true则强制使用CGLIBAopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);}boolean exposeProxy = Boolean.valueOf(sourceElement.getAttribute(EXPOSE_PROXY_ATTRIBUTE));if (exposeProxy) {AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);}}}

这里处理了"proxy-target-class"属性,"proxy-target-class"属性是配置代理的实现方式,Spring AOP 部分使用JDK动态代理,部分使用CGLIB(基于ASM)代理,如果对象实现了接口,而没有继承类,就可以使用JDK的动态代理,生成的对象继承自proxy,实现了父接口。如果对象没有实现任何接口,则使用CGLIB代理(直接操作字节码)。将"proxy-target-class"属性设置为true(默认false)后,就会强制使用CGLIB代理。看下强制使用CGLIB源码:
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);}}

这里面自动设置了exposeProxy = true(解决一些情况写代理无法被增强的问题)。
注册creator以及代理类型的处理之后,继续回到parse方法,跟踪  extendBeanDefinition(element, parserContext);
private void extendBeanDefinition(Element element, ParserContext parserContext) {
//获取前面注册的AnnotationAwareAspectJAutoProxyCreatorBeanDefinition beanDef =parserContext.getRegistry().getBeanDefinition(AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);if (element.hasChildNodes()) {addIncludePatterns(element, parserContext, beanDef);}}

查看 aspectj是否有子元素,存在则进行设置,例如include
 <aop:aspectj-autoproxy proxy-target-class="true" >
 <aop:include/>
 </aop:aspectj-autoproxy>
private void addIncludePatterns(Element element, ParserContext parserContext, BeanDefinition beanDef) {ManagedList<TypedStringValue> includePatterns = new ManagedList<TypedStringValue>();NodeList childNodes = element.getChildNodes();for (int i = 0; i < childNodes.getLength(); i++) {Node node = childNodes.item(i);if (node instanceof Element) {Element includeElement = (Element) node;TypedStringValue valueHolder = new TypedStringValue(includeElement.getAttribute("name"));valueHolder.setSource(parserContext.extractSource(includeElement));includePatterns.add(valueHolder);}}if (!includePatterns.isEmpty()) {includePatterns.setSource(parserContext.extractSource(element));beanDef.getPropertyValues().add("includePatterns", includePatterns);}}

到这里parse的流程就结束了,这里注册了AnnotationAwareAspectJAutoProxyCreator,完成了对aspectj标签的解析,子标签的解析等。下面我们去看下AnnotationAwareAspectJAutoProxyCreator类。看下这个类的层次结构,我们会发现AnnotationAwareAspectJAutoProxyCreator实现了BeanPostProcessor,这就对应到了我们前面看过的,在加载bean的时候,会使用BeanPostProcessor进行处理。当Spring在加载Bean时会在实例化前调用其postpRrocessorAfterInitialization方法(先调用postProcessBeforeInitialization方法),我们看下源码:
/** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (!this.earlyProxyReferences.contains(cacheKey)) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}
这个使用className_beanName作为键值cacheKey,进一步跟踪代码:
/** * 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 (beanName != null && 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;}// 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;}

首先检查缓存,若存在则直接返回对象,然后检验是否是基础类,如Advice子类等,这些类型不做代理,经过这两个步骤之后才进行proxy的创建。首先获取目标对象的所有Advice和Advisor,方法在子类AbstractAdvisorAutoProxyCreator中:

@Overrideprotected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}

获取所有合格的Advisor:
/** * Find all eligible Advisors for auto-proxying this class. * @param beanClass the clazz to find advisors for * @param beanName the name of the currently proxied bean * @return the empty List, not {@code null}, * if there are no pointcuts or interceptors * @see #findCandidateAdvisors * @see #sortAdvisors * @see #extendAdvisors */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;
}
AnnotationAwareAspectJAutoProxyCreator重写了父类的此方法,看下源码
@Overrideprotected 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.advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());return advisors;}

首先调用父类的获取所有候选Advisor方法,然后加入当前容器的Advisor方法。而父类中的方法实现其实是使用了BeanFactoryAdvisorRetrievalHelper的findAdvisorBeans方法,此方法返回所有Advisor.class类型的bean,这里我们就获取了父容器的所有Advisor,然后调用BeanFactoryAspectJAdvisorsBuilder的buildAspectJAdvisors()并放入到advisors数组中。
/** * 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 = null;synchronized (this) {aspectNames = this.aspectBeanNames;if (aspectNames == null) {List<Advisor> advisors = new LinkedList<Advisor>();aspectNames = new LinkedList<String>();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 weavedClass<?> 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 LinkedList<Advisor>();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;}
获取容器内所有的beanName以及类型,过滤掉没有Aspectj注解beanName,对满足条件的beanName进行以下操作
MetadataAwareAspectInstanceFactory factory =new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

并加入缓存中。这里的getAdvisor方法委托给了ReflectiveAspectJAdvisorFactory。
@Overridepublic List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory maaif) {final Class<?> aspectClass = maaif.getAspectMetadata().getAspectClass();final String aspectName = maaif.getAspectMetadata().getAspectName();validate(aspectClass);// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator// so that it will only instantiate once.final MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =new LazySingletonAspectInstanceFactoryDecorator(maaif);final List<Advisor> advisors = new LinkedList<Advisor>();
//getAdvisorMethods(aspectClass)返回不包括pioncut类型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;}

在getAdvisors方法内,我们有了实现了Aspectj的类
for (Method method : getAdvisorMethods(aspectClass)) {Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);if (advisor != null) {advisors.add(advisor);}}

获取此类的所有有Advisor注解(before after around等),然后遍历方法,
private List<Method> getAdvisorMethods(Class<?> aspectClass) {final List<Method> methods = new LinkedList<Method>();ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {@Overridepublic void doWith(Method method) throws IllegalArgumentException {// Exclude pointcutsif (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {methods.add(method);}}});Collections.sort(methods, METHOD_COMPARATOR);return methods;}

在获取AdvisorMethods的方法中,使用了回调函数,排除掉pointcut类型,使用了pointcut注解的方法不会执行,此处跳过。只需要befroe after around等。之后我们对获取声明了AspectJ的类poincut的表达式,并和带有advisor注解的方法一起封装到InstantiationModelAwarePointcutAdvisorImpl对象中并返回对象,缓存起来。
到这里,Spring做了这些事情:在加载bean定义时,使用AspectJAutoProxyBeanDefinitionParser处理了autoproxy的配置,并注册了一个BeanPostProcessor的实现类AspectJAwareAdvisorAutoProxyCreator,在实例化Bean之前,会先调用这些Processsor的方法实例化对象,并返回代理对象(若满足需要),我们获取所有的配置了AspectJ的beanName,获取其所有before after around的method并放入InstantiationModelAwarePointcutAdvisorImpl对象中(后面会进行代理对象的增强实例化)。
0 0
原创粉丝点击