AopNamespaceHandler
配置aop的部分解析器初始化
// AopNamespaceHandler
@Override
public void init() {
// In 2.0 XSD as well as in 2.1 XSD.
registerBeanDefinitionParser("config", new ConfigBeanDefinitionParser());
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());
}
aop:config 的解析
如:
<aop:config>
<aop:pointcut expression="execution(* exam.service..*.*(..))" id="transaction"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="transaction"/>
<aop:aspect ref="aopAdvice">
<aop:before method="beforeSend" pointcut-ref="pointcut" />
<aop:after method="afterSend" pointcut-ref="pointcut" />
</aop:aspect>
</aop:config>
// 通過 ConfigBeanDefinitionParser 來對配置文件中的值進(jìn)行解析
@Override
@Nullable
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compositeDef =
new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compositeDef);
configureAutoProxyCreator(parserContext, element);
List<Element> childElts = DomUtils.getChildElements(element);
for (Element elt: childElts) {
String localName = parserContext.getDelegate().getLocalName(elt);
if (POINTCUT.equals(localName)) {
// pointcut的解析是一個生成一個BeanDefinition并將其id, expression等屬性保存在BeanDefinition中
// BeanDefinition的class是AspectJExpressionPointcut。
// BeanDefinition的scope為prototype。
parsePointcut(elt, parserContext);
}
else if (ADVISOR.equals(localName)) {
parseAdvisor(elt, parserContext);
}
else if (ASPECT.equals(localName)) {
// 解析為beanClass為AspectJPointcutAdvisor的BeanDefinition
parseAspect(elt, parserContext);
}
}
parserContext.popAndRegisterContainingComponent();
return null;
}
aop:aspect標(biāo)簽最終被解析為一個AspectJPointcutAdvisor。
如何生成代理子類
在Bean創(chuàng)建之前生成代理子類
// AbstractAutowireCapableBeanFactory.createBean
// resolveBeforeInstantiation給了機(jī)會讓我們能在初始化bean之前創(chuàng)建代理類
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
if (bean != null) {
return bean;
}
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
// AbstractAutoProxyCreator.postProcessBeforeInstantiation
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
// Spring首先會對當(dāng)前的beanClass進(jìn)行檢查(是否應(yīng)該/可以對其進(jìn)行代理)。
// 不應(yīng)該代理的類分為兩種情況:
// 用于實(shí)現(xiàn)AOP的Spring基礎(chǔ)類,此種情況在isInfrastructureClass方法中完成檢測(單詞Infrastructure正是基礎(chǔ)設(shè)施的意思)。
// 子類定義的應(yīng)該跳過的類,默認(rèn)AbstractAutoProxyCreator的實(shí)現(xiàn)直接返回false,即都不應(yīng)該跳過。
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(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.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
// 校驗(yàn)類型是否是基礎(chǔ)類
protected boolean isInfrastructureClass(Class<?> beanClass) {
boolean retVal = Advice.class.isAssignableFrom(beanClass) ||
Pointcut.class.isAssignableFrom(beanClass) ||
Advisor.class.isAssignableFrom(beanClass) ||
AopInfrastructureBean.class.isAssignableFrom(beanClass);
if (retVal && logger.isTraceEnabled()) {
logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");
}
return retVal;
}
// 當(dāng)前類是否應(yīng)該跳過代理
// AspectJAwareAdvisorAutoProxyCreator.shouldSkip
@Override
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
// TODO: Consider optimization by caching the list of the aspect names
List<Advisor> candidateAdvisors = findCandidateAdvisors();
for (Advisor advisor : candidateAdvisors) {
if (advisor instanceof AspectJPointcutAdvisor &&
((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
return true;
}
}
return super.shouldSkip(beanClass, beanName);
}
Spring跳過的是適用于當(dāng)前bean的Advisor的Advice/Aspect對象
Spring如何找到適用于當(dāng)前bean的Advisor
// 委托給BeanFactoryAdvisorRetrievalHelper
// 首先是從容器中獲取到所有的Advisor示例,然后調(diào)用isEligibleBean方法逐一判斷Advisor是否適用于當(dāng)前bean。
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
Throwable rootCause = ex.getMostSpecificCause();
if (rootCause instanceof BeanCurrentlyInCreationException) {
BeanCreationException bce = (BeanCreationException) rootCause;
String bceBeanName = bce.getBeanName();
if (bceBeanName != null && this.beanFactory.isCurrentlyInCreation(bceBeanName)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping advisor '" + name +
"' with dependency on currently created bean: " + ex.getMessage());
}
// Ignore: indicates a reference back to the bean we're trying to advise.
// We want to find advisors other than the currently created bean itself.
continue;
}
}
throw ex;
}
}
}
}
return advisors;
}
postProcessAfterInitialization
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// 自定義TargetSource,已經(jīng)進(jìn)行過代理子類生成
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
// 基礎(chǔ)類以及跳過類的檢測
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);
// 創(chuàng)建代理
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;
}
尋找Advisor
@Override
@Nullable
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();
}
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;
}
// findAdvisorsThatCanApply最終調(diào)用AopUtils.findAdvisorsThatCanApply
// 對于Advisor的判斷分為了IntroductionAdvisor以及非IntroductionAdvisor兩種情況,從而導(dǎo)致了IntroductionAdvisor在Advisor鏈中總是位于非IntroductionAdvisor前面
// canApply匹配各個不同的IntroductionAdvisor,PointcutAdvisor,放行其他Advisor
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
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) {
// already processed
continue;
}
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
return eligibleAdvisors;
}
Jdk 與 cglib 動態(tài)代理
// DefaultAopProxyFactory.createAopProxy 決定使用何種方式創(chuàng)建代理子類
// 如果指定了(proxy-target-classs設(shè)為true)使用Cglib,那么就會使用Cglib的方式,如果沒有指定(或?yàn)閒alse),那么先回檢測被代理類是否實(shí)現(xiàn)了自己的接口,如果實(shí)現(xiàn)了,那么就采用JDK動態(tài)代理的方式。
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
Jdk動態(tài)代理
// JdkDynamicAopProxy.getProxy
@Override
public Object getProxy(ClassLoader classLoader) {
//找到可以用來進(jìn)行代理的接口
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
//用來代理的接口中是否定義了equals或者是hashCode方法?
//結(jié)果保存在內(nèi)部equalsDefined和hashCodeDefined兩個成員變量中
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
// 這里hanlder傳入了this,在invoke時,調(diào)用的是JdkDynamicAopProxy.invoke
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
aop:scoped-proxy
<bean id="userPreferences" class="com.foo.UserPreferences" scope="session">
<aop:scoped-proxy/>
</bean>
<bean id="userManager" class="com.foo.UserManager">
<property name="userPreferences" ref="userPreferences"/>
</bean>
如果沒有使用aop:scoped-proxy的話,對于ref屬性,只會在userManager初始化時注入一次。這會造成什么問題呢?以session的Scope為例,因?yàn)橹粫⑷胍淮?,所以,userManager引用的始終是同一個userPreferences對象,即使現(xiàn)在可能已經(jīng)過時了。
aop:scoped-proxy配置可以使userManager引用的其實(shí)是一個對代理的引用,所以可以始終獲取到最新的userPreferences。其作用和注解@ScopedProxy相同。
// DefaultBeanDefinitionDocumentReader.processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
// 將bdHolder 交給BeanDefinitionParserDelegate進(jìn)行裝飾
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
// BeanDefinitionParserDelegate.decorateIfRequired
public BeanDefinitionHolder decorateIfRequired(
Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {
String namespaceUri = getNamespaceURI(node);
if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
if (handler != null) {
BeanDefinitionHolder decorated =
// 創(chuàng)建一個新的BeanDefinition對象,beanName為被代理的bean的名字,被代理的bean名字為scopedTarget.原名字。被代理的bean將被注冊到容器中。
handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
if (decorated != null) {
return decorated;
}
}
else if (namespaceUri.startsWith("http://www.springframework.org/")) {
error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node);
}
else {
// A custom namespace, not to be handled by Spring - maybe "xml:...".
if (logger.isDebugEnabled()) {
logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]");
}
}
}
return originalDef;
}
參考:
Seaswalker的Spring-analysis:
github地址