咱们总结出AOP公式java
本质都是在内存中生成了新的字节码类。spring
这节咱们看看事务是如何利用AOP实现的。缓存
@EnableTransactionManagement的@Import(TransactionManagementConfigurationSelector.class)引入TransactionManagementConfigurationSelector.class。此类app
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME};
default:
return null;
}
}
复制代码
PROXY:状况下,会注册两个类:ide
实现了ImportBeanDefinitionRegistrar。其接口方法registerBeanDefinitions会向仓库注册Bean定义源码分析
InfrastructureAdvisorAutoProxyCreator。 InfrastructureAdvisorAutoProxyCreator
继承了AbstractAdvisorAutoProxyCreator间接继承了AbstractAutoProxyCreator
post
在AOP代理生成那一节,咱们讲过。AnnotationAwareAspectJAutoProxyCreator
也是间接继承了AbstractAutoProxyCreator
。ui
在AOP实现原理中AbstractAutoProxyCreator
作了大部分工做。this
从这一点看,事务代理对象建立过程,与AOP代理对象过程是同样的,关键就在这个AbstractAutoProxyCreator类spa
是一个@Configuration。有三个@Bean注解方法。
@Configuration
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor() {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource());
advisor.setAdvice(transactionInterceptor());
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
复制代码
1.BeanFactoryTransactionAttributeSourceAdvisor:
首先:transactionAdvisor()方法会向仓库中注册一个BeanFactoryTransactionAttributeSourceAdvisor。
从其继承关系上看,他是一个Advisor,而且仍是PointcutAdvisor.关于Advisor,上节咱们分析过他是封装了(Advice+Pointcut)
既然都有了Advisor了,那Advice和Pointcut在哪里呢?
BeanFactoryTransactionAttributeSourceAdvisor有一个pointcut 属性,会new 一个TransactionAttributeSourcePointcut。
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
复制代码
从其继承关系,咱们能够看出他其实就是一个Pointcut。
至此,就剩下Advice没有被发现。
2.TransactionAttributeSource: 其次:transactionAttributeSource()会向仓库中注册一个AnnotationTransactionAttributeSource。这个AnnotationTransactionAttributeSource干吗用的呢?
BeanFactoryTransactionAttributeSourceAdvisor.setTransactionAttributeSource(transactionAttributeSource())
属性值
private TransactionAttributeSource transactionAttributeSource;
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
TransactionAttributeSourcePointcut的matche方法
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
复制代码
AnnotationTransactionAttributeSource对象会赋值给BeanFactoryTransactionAttributeSourceAdvisor的transactionAttributeSource
属性。pointcut
属性初始化时,new 一个TransactionAttributeSourcePointcut类
并实现getTransactionAttributeSource()
方法,getTransactionAttributeSource()
方法正好返回了transactionAttributeSource
属性。
也就是说TransactionAttributeSourcePointcut的getTransactionAttributeSource()方法返回的是AnnotationTransactionAttributeSource
3.TransactionInterceptor : 最后:transactionInterceptor()方法,会向仓库中注册一个TransactionInterceptor类。
TransactionInterceptor从继承关系看他是一个Advice. 也就是加强器,是对事务真正处理地方。
有了Advice+Pointcut。Advice+Pointcut = Advisor 。 Advisor+TargetSource = Advised
有了Advised ,这样spring事务不正是套用了AOP的基础吗。
在AOP源码分析那一节,咱们讲过,postProcessAfterInitialization后置初始化方法中,wrapIfNecessary 知足条件,才建立代理。
@Override
public 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;
}
复制代码
而这个条件就是:getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 可以获取适用于当前bean的Advisor
咱们回顾上节:
getAdvicesAndAdvisorsForBean 通过AbstractAdvisorAutoProxyCreator.findEligibleAdvisors
的调用,AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass)
的调用,最终会调用AopUtils.canApply
来判断某个Advisor是否适用于当前类。
咱们来看看canApply方法
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
// It doesn't have a pointcut so we assume it applies.
return true;
}
}
复制代码
上文提到,
因此此处会走: canApply(pca.getPointcut(), targetClass, hasIntroductions)分支。
pca.getPointcut()
返回的是TransactionAttributeSourcePointcut
进一步分析重载方法canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)
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();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
classes.add(targetClass);
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if ((introductionAwareMethodMatcher != null &&
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
复制代码
TransactionAttributeSourcePointcut
的父类StaticMethodMatcherPointcut.classFilter= ClassFilter.TRUE
表示类检查所有经过abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (targetClass != null && TransactionalProxy.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
}
复制代码
matches方法会调用getTransactionAttributeSource()
获取一个TransactionAttributeSource
对象,经过TransactionAttributeSource.getTransactionAttribute(method, targetClass)
,来判断适应性。
关于getTransactionAttributeSource()
上文讲过。会返回一个AnnotationTransactionAttributeSource
实例对象。
也就是说:TransactionAttributeSourcePointcut 的 matches()方法是经过AnnotationTransactionAttributeSource.getTransactionAttribute(method, targetClass)来实现的。
来看看getTransactionAttribute()方法
@Override
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
// First, see if we have a cached value.
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// Value will either be canonical value indicating there is no transaction attribute,
// or an actual transaction attribute.
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
return null;
}
else {
return cached;
}
}
else {
// We need to work it out.
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// Put it in the cache.
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isDebugEnabled()) {
logger.debug("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
}
复制代码
这里用了一个缓存,但重点在这个TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
protected TransactionAttribute computeTransactionAttribute(Method method, Class<?> targetClass) {
// Don't allow no-public methods as required.
// 非public方法事务不生效。
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
}
// Ignore CGLIB subclasses - introspect the actual user class.
Class<?> userClass = ClassUtils.getUserClass(targetClass);
// The method may be on an interface, but we need attributes from the target class.
// If the target class is null, the method will be unchanged.
// 获取真实的方法(有接口方法的,要获取实现类上的那个方法)
Method specificMethod = ClassUtils.getMostSpecificMethod(method, userClass);
// If we are dealing with method with generic parameters, find the original method.
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
// First try is the method in the target class.
//首先查看实现类方法上是否有@Transactional注解
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
// Second try is the transaction attribute on the target class.
//其次查看实现类方法所在类上是否有@Transactional注解
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
if (specificMethod != method) {
// Fallback is to look at the original method.
//还不行去看接口方法上是否有@Transactional注解
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// Last fallback is the class of the original method.
//最后看接口上是否有@Transactional注解
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
复制代码
由此:咱们们也终于知道,@Transactional注解的查找顺序,实现类方法--》实现类--》接口方法--》接口 咱们在这四个地方添加@Transactional注解都会使事务生效。
在这四个地方任一一个地方找到了@Transactional注解,说明BeanFactoryTransactionAttributeSourceAdvisor
适用于当前类,getAdvicesAndAdvisorsForBean 的返回不为空。接下来就能够建立动态代理了。
// 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;
}
复制代码
createProxy()方法,在spring源码系列8:AOP源码解析之代理的建立一节咱们一节分析过了。
最终的结果就是经过 CglibAopProxy. getProxy()返回代理对象 或者 JdkDynamicAopProxy. getProxy()返回代理对象
spring事务,就是在spring AOP基础上实现的。 经过定义一个适用于事务的Advisor(Advice+Pointcut)完美的套用AOP的东西,实现了事务。
咱们看看这个公式:
试想,若是咱们可不能够利用这个公式也能建立出一个相似事务的东西呢?