Spring源码阅读(六)—AOP获取增强
本文主要分析了AOP功能实现中的自定义标签解析和增强的获取
个人主页:tuzhenyu’s page
原文地址:Spring源码阅读(六)—AOP获取增强
(0) Spring AOP实现的主要步骤
解析AOP自定义标签,注册AnnotationAwareAspectJAutoProxyCreator自动代理创建器
获取增强
创建代理
(1) 解析AOP自定义标签
- AOP功能实现的最基本入口在XML配置文件中的AOP功能的开启;
<aop:aspectj-autoproxy>
- 在容器初始化解析XML配置文件会将标签分为普通标签和自定义标签分别进行解析处理.
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
- aop标签属于自定义标签会调用相应的处理器进行处理
public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(ele);
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler == null) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
return null;
}
return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
}
- 从NamespaceHandler中获取aop的aspectj-autoproxy对应的解析器是AspectJAutoProxyBeanDefinitionParser
public void init() {
this.registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
this.registerBeanDefinitionParser("aspectj-autoproxy", new AspectJAutoProxyBeanDefinitionParser());
this.registerBeanDefinitionDecorator("scoped-proxy", new ScopedProxyBeanDefinitionDecorator());
this.registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
}
- 所有解析器都是由 BeanDefinitionParser 接口的统一实现,入口都是从 parse函数开始的
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
registerAspectJAnnotationAutoProxyCreatorIfNecessary 函数是 AnnotationAwareAspectJAutoProxyCreator 注册的地方,也是注册的主要逻辑实现的地方。主要实现了一下三个功能:
AnnotationAwareAspectJAutoProxyCreator的注册或升级
对于 proxy-target-class 以及 expose-proxy 属性的处理,用于判断是否强制使用CGLIB代理模式
注册组件并通知,便于监听器作进一步处理.
public static void registerAspectJAnnotationAutoProxyCreatorIfNecessary(ParserContext parserContext, Element sourceElement) {
BeanDefinition beanDefinition = AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement));
useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement);
registerComponentIfNecessary(beanDefinition, parserContext);
}
- 至此,aop自定义标签完成了解析,同时也将AnnotationAwareAspectJAutoProxyCreator注册到了处理器中.
(2) AOP代理实现的入口
- spring 容器启动,在每个bean实例话过程中会首先尝试到缓存中获取,获取上失败后会调用createBean()方法从头创建bean.在调用doCreateBean()方法正式创建之前会调用resolveBeforeInstantiation()方法尝试是否创建代理类替代真正的实例,如果创建成功则直接返回跳过后续的真正创建过程,如果创建失败则继续创建bean实例.
Object beanInstance;
try {
beanInstance = this.resolveBeforeInstantiation(beanName, mbd);
if(beanInstance != null) {
return beanInstance;
}
} catch (Throwable var6) {
throw new BeanCreationException(mbd.getResourceDescription(), beanName, "BeanPostProcessor before instantiation of bean failed", var6);
}
- 在resolveBeforeInstantiation()方法中会调用提前注册的处理器AnnotationAwareAspectJAutoProxyCreator的postProcessAfterInitialization()方法实现代理的创建
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if(!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
if(!mbd.isSynthetic() && this.hasInstantiationAwareBeanPostProcessors()) {
Class targetType = this.determineTargetType(beanName, mbd, new Class[0]);
if(targetType != null) {
bean = this.applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if(bean != null) {
bean = this.applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = Boolean.valueOf(bean != null);
}
return bean;
}
- postProcessAfterInitialization()方法调用wrapIfNecessary()方法进行代理的实现
public Object <strong>postProcessAfterInitialization</strong>(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()方法实现了aop实现的主要逻辑,调用getAdvicesAndAdvisorsForBean()提取当前bean 的所有增强方法,然后调用createProxy()方法创建具体代理.
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.containsKey(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;
}
Object[] specificInterceptors = <strong>getAdvicesAndAdvisorsForBean</strong>(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;
}
(3) AOP增强的获取
getAdvicesAndAdvisorsForBean()主要是通过调用findEligibleAdvisors()方法用来获取该bean的增强列表.主要步骤包括:
寻找所有增强
从所有增强中获取适合该bean的增强.
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;
}
findCandidateAdvisors()方法是用来获取所有的增强,主要步骤包括:
获取所有在beanFactory中注册的beanName
遍历所有的beanName,判断是否为声明为AspectJ的类,如果是则进行进一步处理
对标记为AspectJ注解的类进行增强器的提取
将提取结果放入缓存
protected List<Advisor> findCandidateAdvisors() {
List advisors = super.findCandidateAdvisors();
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
List aspectNames = null;
synchronized(this) {
aspectNames = this.aspectBeanNames;
if(aspectNames == null) {
LinkedList var16 = new LinkedList();
LinkedList var15 = new LinkedList();
String[] var17 = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
String[] var18 = var17;
int var19 = var17.length;
for(int var7 = 0; var7 < var19; ++var7) {
String beanName = var18[var7];
if(this.isEligibleBean(beanName)) {
Class beanType = this.beanFactory.getType(beanName);
if(beanType != null && this.advisorFactory.isAspect(beanType)) {
var15.add(beanName);
AspectMetadata amd = new AspectMetadata(beanType, beanName);
if(amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
BeanFactoryAspectInstanceFactory factory1 = new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
List classAdvisors = this.advisorFactory.getAdvisors(factory1);
if(this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
} else {
this.aspectFactoryCache.put(beanName, factory1);
}
var16.addAll(classAdvisors);
} else {
if(this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name \'" + beanName + "\' is a singleton, but aspect instantiation model is not singleton");
}
PrototypeAspectInstanceFactory var20 = new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, var20);
var16.addAll(this.advisorFactory.getAdvisors(var20));
}
}
}
}
this.aspectBeanNames = var15;
return var16;
}
}
- 调用findAdvisorsThatCanApply()方法从所有增强中获取适合该bean的增强
protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
List var4;
try {
var4 = AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
} finally {
ProxyCreationContext.setCurrentProxiedBeanName((String)null);
}
return var4;
}
(4) 总结
AOP功能的实现是从XML配置文件中的aop标签解析开始的,标签的解析会注册代理自动创建器用于后续的调用.当从容器中尝试获取bean的时候会在真正创建bean之前尝试创建代理,创建代理主要包括增强的获取和代理的创建两部分,这篇博文主要分析了增强获取的主要流程.