对于Spring Aop, 可以从三个方面进行解析.
1. Spring配置文件或者@AspectJ主角中的Aop配置如何被解析? Advisor
Spring Aop是使用动态代理来实现的,即将Aspect(切面)的内容织入动态代理类中: xx$Proxy
那么就有2个疑问:
2. Spring Aop要生成动态代理类$Proxy, 是怎么参与到BeanFactory.getBean(beanName)中的流程的? getBean()中是根据beanDefinition来加载Class<?>,并生成对应的类实例的.
Spring要想实现Aop,那么生成的实例就应该是动态代理类$Proxy的实例.而不是原始类的实例.
3. Spring Aop中具体是怎么生成动态代理类$Proxy的? Jdk 动态代理和Cglib动态代理都是怎么参与进来的: Spring Aop动态代理具体实现过程.
Spring Aop配置如何被解析?
在Spring中关于Aop的配置有spring xml和注解2种方式进行配置,先看spring xml配置的方式如何解析. 这个看起来比较简单一点.
<aop:config>
<aop:pointcut expression="execution(public *com.briup.aop.service.*.*(..))" id="myPointCut"/>
<aop:aspect id='aspect' ref='切面bean'>
<aop:before method='切面bean中的方法' pointcut-ref='切点ref'/>
<aop:after method='xx' pointcut-ref='xxRef'/>
</aop:aspect>
<aop:advisor advisor-ref='adviceBean' pointcut-ref='pointcutDefinition'/>
</aop:config>
通过阅读Spring读取xml得到BeanDefinition的源码可以得到, 关于xml配置的解析都是NamespaceHandler的实现类来完成的.
在AopNamespanceHanlder中完成了对aop:xxx 命名空间下的配置解析.
@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下的配置都是用ConfigBeanDefinitionParser实例来解析的.
在ConfigBeanDefinitionParser中有parsePointcut, parseAdvisor , parseAspect方法来解析aop:config中的配置.
最终会得到pointcutBeanDefinition, adviceBeanDefinition, advisorBeanDefinition. 得到的beanDefinition会注册到BeanDefinitionRegistry: beanFactory中. 这样在getBean()的时候就可以从beanFactory中获取到Aop配置相关的beanDefitnion.
具体的解析过程参考:[Spring ConfigBeanDefinitionParse源码解析] ,在这篇文章中只描述各个组件之间的关系.
Spring Aop是如何参与到getBean的流程
在Spring ConfigBeanDefinitionParser中有这样一段代码: (也是看了好久,一直还不知道是干什么的)
configureAutoProxyCreator(parserContext, element)
追根溯源AopNamespaceUtils -> AopConfigUtils, 最终发现是向beanFacotry:BeanDefinitionRegistry中注册了一个
beanName: ‘org.springframework.aop.config.internalAutoProxyCreator’
beanClass: AspectJAwareAdvisorAutoProxyCreator
的beanDefinition.
查看AspectJAwareAdvisorAutoProxyCreator的类图, 可以看到它实现了SmartInstantiationAwareBeanPostProcessor.
既然知道了它实现了SmartInstantiationAwareBeanPostProcessor, 那么就知道了它肯定会参与到beanFactory.getBean()的流程中: 在getBean()提供了一系列的Hook.
参考文章: [Spring AbstractBeanFacotyr.getBean流程]
Haha,这里就知道了上面注册的AspectJAwareAdvisorAutoProxyCreator是干什么的了,就是为了参与到Spring getBean()的流程来创建Aespect切入的bean.
AbstractAutoProxyCreator: 通过实现SmartInstantiationAwareBeanPostProcessor: postProcessBeforInstantiation 参与到getBean()中创建bean instance的流程中来.
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
Object cacheKey = getCacheKey(beanClass, beanName);
if (beanName == null || !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.
if (beanName != null) {
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
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;
}
在AbstractAutoProxyCreator中就描述了怎么生成Aop切面切入之后的proxy bean instance.
AbstractAutoProxyCreator.getAdvicesAndAdvisorsForBean(beanClass,beanName,targetSource): 用来获取bean需要切入的切面.
AbstractAutroProxyCreator.createProxy(beanClass, beanName, specificInterceptors,targetSource): 描述了如何根据advisor来构建proxy instance
AbstractAutoProxyCreator定义了一套模板, 具体getAdvicesAndAdvisorsForBean的过程在子类AbstractAdvisorAutoProxyCreator中被实现.
AbstractAdvisorAutoProxyCreator:
@Override
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, 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;
} protected List<Advisor> findCandidateAdvisors() {
return this.advisorRetrievalHelper.findAdvisorBeans();
}
最终findCandidateAdvisors的实现委托给了advisorRetrievalHelper.findAdvisorBeans().
/**
* Find all eligible Advisor beans in the current bean factory,
* ignoring FactoryBeans and excluding beans that are currently in creation.
* @return the list of {@link org.springframework.aop.Advisor} beans
* @see #isEligibleBean
*/
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = null;
synchronized (this) {
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 LinkedList<Advisor>();
}
List<Advisor> advisors = new LinkedList<Advisor>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isDebugEnabled()) {
logger.debug("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;
if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {
if (logger.isDebugEnabled()) {
logger.debug("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;
}
通过BeanFactoryAdvisorRetrievalHelper.findAdvisorBeans()中的这句代码:
BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
可以知道, findAdvisor的过程也是从beanFactory:BeanDefinitionRegistry中获取Advisor的BeanDefiniton, 然后getBean().
这里也和前面ConfigBeanDefinitionParser中将Adviso 的BeanDefinition注册到beanFactory:BeanDefinitionRegistry的过程联系起来.
AbstractAdvisorAutoProxyCreator在findCandidateAdvisors后, 会判断哪些advisor可以切入到beanClass中.
findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 就是判断哪些advisor可以应用到beanClass的.
具体是如何判断是否可以应用的,后面再描述
FAQ:
1. 关于类图中
AspectJAwareAdvisorAutoProxyCreator,
AnnotationAwareAspectJAutoProxyCreator
InfrastructureAdvisorAutoProxyCreator
之间的关系. ??
Answer:
在AopConfigUtils中,定义了一个优先级列表:
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>();
/**
* Setup the escalation list.
*/
static {
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}
在注册AutoProxyCreator实例的时候优先级高的会替换优先级低的注册到beanFactor:BeanDefinitionRegistry中.
public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) {
return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source);
}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;
}
AnnotationAwareAspectJAutoProxyCreator比AspectJAwareAdvisorAutoProxyCreatory优先级高.
AnnotationAwareAspectJAutoProxyCreator是AspectJAwareAdvisorAutoProxyCreatory的子类.
在AnnotationAwareAspectJAutoProxyCreator中,覆盖实现了findCandidateAdvisors方法:
@Override
protected 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;
}
在aspectJAdvisorsBuilder.buildAspectJAdvisors()中解析了@AspectJ中配置的Aop配置.
AnnotationAwareAspectJAutoProxyCreator不仅具有了AspectJAwareAdvisorAutoProxyCreator的功能,还解析了@AspectJ配置的Aop, 构建了Advisor.
AnnotationAwareAspectJAutoProxyCreator在AspectJAutoProxyBeanDefinitionParser中被注册.
lass AspectJAutoProxyBeanDefinitionParser implements BeanDefinitionParser {
@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);
extendBeanDefinition(element, parserContext);
return null;
}
在AspectJAutoProxyBeanDefinitionParser中不负责解析工作,真正的解析工作都放到AnnotationAwareAspectJAutoProxyCreator中实现, 委托给aspectJAdvisorsBuilder.
Spring Aop在创建Proxy的时候是怎么实现的?
现在已经有了Advisor, 下面就是怎么创建proxy instance的过程了.
在AbstractAutoProxyCreator中可以看到是在createProxy()中完成对Aop proxy instance的创建. AbstractAutoProxyCreator.createProxy():
protected Object createProxy(Class<?> beanClass, String beanName, Object[]
specificInterceptors, TargetSource targetSource) {
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()){
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor :advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()){
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
通过阅读上面的代码可以发现是通过ProxyFactory实例来创建proxy instance的.
这里我们先看看ProxyFactory的类图:(因为发现ProxyFactory并不是一个简单的工厂)
通过阅读上面的源码AbstractAutoProxyCreator.createProxy()和对ProxyFactory整个类图的理解.可以知道Aop proxy instance的创建过程是通过AopProxy类来完成的.
在使用ProxyFactory.geteProxy()的时候, 使用的是默认的DefaultAopProxyFactory来创建的AopProxy实例. (ProxyFactory extends ProxyCreatorSupport . ProxyCreatorSupport默认使用的DeafultAopProxyFactory).
那么我们再来看看是怎么创建AopProxy的.
在ProxyCreatorSupport中
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
上面getAopProxyFactory()就获得默认的DefaultAopProxyFactory或者自定义AopProxyFactory.
使用getAopProxyFactory().createAopProxy(this)来创建Aopproxy, 是因为该类还兼职了AdvisedSupport功能.
DefaultAopProxyFactory.createAopProxy(AdvisedSupport config):
@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("TargetSourcecannot 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);
}
}
阅读上面DefaultAopProxyFactory.createAopProxy(AdvisedSupport config)可以看到是根据不同的配置来选择创建不同的AopProxy类实例.
?? 网上说的optimize=’true’的智能优化策略在哪里?? 我只看出来了如果目标类是接口或者是通过Proxy.newProxyInstance创建的jdk代理类则继续使用JdkDynamicAopProxy.
Answer: TODO
这里的AopProxy为Spring framework提供了统一的创建proxy instance的接口:
+ getProxy()
+ getProxy(classLoader)
有通过jdk动态代理来实现JdkDynamicAopProxy; 也用通过Cglib代理技术来实现的CglibAopProxy/ObjenesisCglibAopProxy.
Ps: 这里的ObjenesisCglibAopProxy是采用了Objenesis技术: Obenesis是弥补jdk不足而创造的. Class.newInstnce贼没有午餐构造函数是不能生成对象的,这里objenesis就可以派上用场. (这个只是其中一点)具体的关于Objenesis在后面进行描述.
Objenesis在Spring 4.0+中被引入
JdkDynamicAopProxy和ObjenesisCglibAopProxy/CglibAopProxy在
DefaultAopProxyFactory中被创建. (上文中提到的代码已经描述过)
JdkDynamicAopProxy:
@Override
public Object getProxy() {
return getProxy(ClassUtils.getDefaultClassLoader());
}
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()){
logger.debug("Creating JDK dynamic proxy: target source is "
+ this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces =AopProxyUtils.completeProxiedInterfaces(this.advised);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看到在JdkDynamicAopProxyFactory中是使用的java.lang.reflect.Proxy 来完成对proxy instance的创建的.
通过还看到JdkDynamicAopProxyFactory实现了InvocationHandler接口: 这里是jdk Proxy需要的.
CglibAopProxyFactory:
@Override
public Object getProxy() {
return getProxy(null);
}
@Override
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
// TargetSource.getTarget() failed
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
上面的代码中也可以看到在CglibAopProxy中是使用了
org.springframework.cglib.proxy.Enhancer 来创建的proxy instance.
到这里,关于Spring AOP的相关的疑问就已经解答完了. 如果有新的疑问也可以和我沟通.
上面已经对Spring AOP有了深刻的认知,那么下面就对Spring中比较经典的AOP应用案例:
Spring Aop: tx:事务解读一下.
Spring AOP tx:事务相关配置如何被解析的
通过前面的阅读Spring AOP的配置是如何被解析的: aop:xxx 命名空间是被AopNamespaceHandler解读的. 那么可以知道tx:xxx命名空间是被TxNamespaceHandler解读的.
Spring中关于事务的配置:
<bean id="transactionManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager"
abstract="false" lazy-init="default" autowire="default"
dependency-check="default">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<!-- <tx:method name="*" propagation="true" />-->
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="allManagerMethod"
expression="execution(* com.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice"
pointcut-ref="allManagerMethod" />
</aop:config>
TxNamespaceHandler:
@Override
public void init() {
registerBeanDefinitionParser("advice", new TxAdviceBeanDefinitionParser());
registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
registerBeanDefinitionParser("jta-transaction-manager", new JtaTransactionManagerBeanDefinitionParser());
}
可以看到tx:advice是被TxAdviceBeanDefinitionParser解析的.
<tx: annotation-driven>是用来处理注解事务@Transactional的, 这里暂时不用讨论,大同小异. 和@Pointcut差不太多. 先了解XML配置是如何解析的,后面注解式的解析只是解析方式不一样而已.
tx:jta-transacation-manager是用来解析分布式事务相关的,一般的情况下也用到到分布式事务. 后面有空在对这方面进行解析.
Spring AOP非tx:命名空间的声明式事务解析
在阅读tx:xxx配置方式配置事务的时候,发现了另外一种Spring声明式事务配置的方式:
<bean
id="baseTransactionProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
abstract="true">
<property name="transactionManager" ref="transactionManager"/>
<property name="transactionAttributes">
<props>
<prop key="insert*">PROPAGATION_REQUIRED</prop>
<prop key="update*">PROPAGATION_REQUIRED</prop>
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>
<bean id="myProxy" parent="baseTransactionProxy">
<property name="target" ref="myTarget"/>
</bean>
<bean id="yourProxy" parent="baseTransactionProxy">
<property name="target" ref="yourTarget"/>
</bean>
这里是TransactionProxyFactoryBean进行处理的