根据方法名配置全局事务,基于AOP的Advisor理解
@
aop?
前面都是一些简单的AOP调用相关的代码,关心怎么用之间看后面事务。
不改变源码的的前提下,在一个方法的前后插入一段代码块——汉堡包模型方法加强。
搞清问题
spring怎么知道
往哪个类的哪个方法前后插入代码块?配置切点
//配置切入点,该方法无方法体,主要为方便同类中其他方法使用此处配置的切入点
@Pointcut("execution(* com.pikadog.micro.service..*(..))")
public void aspect() {
}
方法执行到什么时候,插入什么样的代码块?配置通知模式
//配置环绕通知,使用在方法aspect()上注册的切入点
@Around("aspect()")
public Object around(JoinPoint joinPoint) {
long start = System.currentTimeMillis();
Object proceed = null;
try {
proceed = ((ProceedingJoinPoint) joinPoint).proceed();
long end = System.currentTimeMillis();
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms!");
return proceed;
} catch (Throwable e) {
long end = System.currentTimeMillis();
log.info("around " + joinPoint + "\tUse time : " + (end - start) + " ms with exception : " + e.getMessage());
}
return proceed;
}
转化一下就是这两个问题
1.切面的配置是如何被读到spring里面的
2.spring是如何应用这些配置生成代理类的
切面的配置是如何被读到spring里面的
java类的生命周期
指一个class文件从加载到卸载的全过程,类的完整生命周期包括7个部分:加载——验证——准备——解析——初始化——使用(实例化-垃圾收集-对象终结)——卸载
Spring bean的实例化
实例化(new)一个对象(通常是调用了无参构造方法)的流程
- set方法给属性赋值(ref属性)
- BeanNameAware 知道自己的名字了
- BeanFactoryAware 知道自己由哪个工厂类创建出来
- ApplicationContextAware
- BeanPostProcessor的before方法
- InitializingBean
- 自定义的init方法
- BeanPostProcessor的after方法
- DisposableBean方法
- 自定义的destroy方法
这里第五步的
BeanPostProcessor
//后置处理器
//在spring的Bean对象实例化和依赖注入完毕之后,在显式调用初始化方法的前后添加我们自己的逻辑。
public interface BeanPostProcessor {
@Nullable
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
@Nullable
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
这个后置处理器的实现类很多,在各个BeanPostProcessor中有一个AnnotationAwareAspectJAutoProxyCreator,spring会在该类的 postProcessBeforeInitialization 里进行Advisor的初始化
继承关系是这样的
AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware
SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor
InstantiationAwareBeanPostProcessor extends BeanPostProcessor
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator{
//注意这里的findCandidateAdvisors和buildAspectJAdvisors,是生成advisor的关键方法,后面会写
protected List<Advisor> findCandidateAdvisors() {
List<Advisor> advisors = super.findCandidateAdvisors();
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
}
spring在创建一个类之前,会看一下有没有配置切面,如果有,就把配置转换成一个个的advisor,然后缓存起来,方便后面需要生成代理类的时候直接使用。
advisor生成流程
AbstractAutowireCapableBeanFactory——createBean()->resolveBeforeInstantiation()——
AbstractAutoProxyCreator——postProcessBeforeInstantiation()——
AspectJAwareAdvisorAutoProxyCreator——shouldSkip()
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
//spring在这里进行Advisor的初始化,这里其实是AnnotationAwareAspectJAutoProxyCreator执行了父类的postProcessBeforeInstantiation方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = this.getCacheKey(beanClass, beanName);
//是否处理过
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//没有处理过,判断是否应该跳过,跳过的话就put false,不创建advisor
if (this.isInfrastructureClass(beanClass) || this.shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
TargetSource targetSource = this.getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
//这里就把目标类的代理类型生成以后放进缓存方便后续取用
//获取目标类的Advisors,相当于执行目标类的目标方法之前要通过这些设置好的拦截器
Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
//根据目标类,目标类的拦截器们,生成代理类
Object proxy = this.createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
} else {
return null;
}
}
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//判断类名是不是.ORIGINAL结尾的 不是返回false,基本都不是
return AutoProxyUtils.isOriginalInstance(beanName, beanClass);
}
}
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
//上面的shouldSkip会先走到这里
protected boolean shouldSkip(Class<?> beanClass, String beanName) {
//获取注册进容器的切点,得到候选Advisor列表
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
Iterator var4 = candidateAdvisors.iterator();
//循环
Advisor advisor;
do {
//如果是最后一个,循环走完了,掉父类的判断是不是.ORIGINAL结尾的类
if (!var4.hasNext()) {
return super.shouldSkip(beanClass, beanName);
}
advisor = (Advisor)var4.next();
//advisor的AspectName就是定义切面所在类的类名
//自定义的advisor都是InstantiationModelAwarePointcutAdviso
//当切面类型是AspectJPointcutAdvisor或者当前类就是定义切面的那个类,返回true
} while(!(advisor instanceof AspectJPointcutAdvisor) || !((AspectJPointcutAdvisor)advisor).getAspectName().equals(beanName));
return true;
}
}
//getAdvicesAndAdvisorsForBean是AbstractAutoProxyCreator的抽象方法,这里执行AbstractAdvisorAutoProxyCreator的实现
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//发现目标类的符合条件的Advisors,没有的话就返回不生成代理
List<Advisor> advisors = this.findEligibleAdvisors(beanClass, beanName);
return advisors.isEmpty() ? DO_NOT_PROXY : advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取候选的Advisors,相当于所有切面
List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
//获取符合条件的,从candidateAdvisors里面选择符合当前bean条件的
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
this.extendAdvisors(eligibleAdvisors);
//设置拦截器的时候根据优先级排个序
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
}
//找到实现了Advisor接口的类,并返回。Advisor列表
public class BeanFactoryAdvisorRetrievalHelper{
public List<Advisor> findAdvisorBeans() {
//获取缓存里面的实现了Advisor的类
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
//没有的话就获取所有继承了Advisor的类名并且缓存起来
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList();
} else {
List<Advisor> advisors = new ArrayList();
String[] var3 = advisorNames;
int var4 = advisorNames.length;
//循环advisorNames
for(int var5 = 0; var5 < var4; ++var5) {
String name = var3[var5];
if (this.isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
} else {
try {
//主要就是这行代码,找到实现了Advisor接口的类,并返回。
advisors.add(this.beanFactory.getBean(name, Advisor.class));
} catch (BeanCreationException var11) {
Throwable rootCause = var11.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: " + var11.getMessage());
}
continue;
}
}
throw var11;
}
}
}
}
return advisors;
}
}
}
public class BeanFactoryAspectJAdvisorsBuilder {
//当切面配置是用注解进行注册的,上面的find方法发现继承了Advisor的类就不行了
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
synchronized(this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList();
List<String> aspectNames = new ArrayList();
//找到所有的类(因为是Object所以基本上就是所有被spring管理的类)
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(this.beanFactory, Object.class, true, false);
String[] var18 = beanNames;
int var19 = beanNames.length;
for(int var7 = 0; var7 < var19; ++var7) {
String beanName = var18[var7];
if (this.isEligibleBean(beanName)) {
Class<?> beanType = this.beanFactory.getType(beanName, false);
//是否是Aspect(比如含有@Aspect注解)
if (beanType != null && 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);
//生成Advisor
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 {
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();
} else {
List<Advisor> advisors = new ArrayList();
Iterator var3 = aspectNames.iterator();
while(var3.hasNext()) {
String aspectName = (String)var3.next();
List<Advisor> cachedAdvisors = (List)this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
} else {
MetadataAwareAspectInstanceFactory factory = (MetadataAwareAspectInstanceFactory)this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
}
public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFactory implements Serializable {
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
this.validate(aspectClass);
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory = new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList();
//获得切面注解配置方法
Iterator var6 = this.getAdvisorMethods(aspectClass).iterator();
while(var6.hasNext()) {
Method method = (Method)var6.next();
//每个配置方法生成一个Advisor
Advisor advisor = this.getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new ReflectiveAspectJAdvisorFactory.SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
Field[] var12 = aspectClass.getDeclaredFields();
int var13 = var12.length;
for(int var14 = 0; var14 < var13; ++var14) {
Field field = var12[var14];
Advisor advisor = this.getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
}
所以总结来说就是所有的被spring管理起来的bean在完成对象实例化和依赖注入完毕之后,会通过一个BeanPostProcessor,在里面判断这个类有没有进行切面的配置,比如有没有继承Advisor或者通过注解写了切面通知方法。如果有就每一个切面配置生成一个Advisor,缓存起来。在执行方法的时候会根据我们之前生成的各个Advisor对应的切入点,判断下当前的方法是否满足该切入点。如果满足,将其适配为MethodInterceptor 接口并返回。
应用切面设置全局事务
被@Transactional注解修饰的方法其实相当于一个在执行的时候,代理也生成了一个Advisor拦截器拦截在修饰方法之前。
先是切换数据库的拦截器,配置了切点和拦截规则

切换数据库的拦截规则:执行方法之前根据方法名做主从切换

根据方法名配置默认全局事务,根据Advisor的setOrder进行执行顺序排序

事务执行优先级
这样配置完全局事务的优先级依次分别为:数据库切换、根据方法名创建事务、@Transactional注解配置事务
那么如果一个service方法 上面有@Transactional 如何判断用了主库从库?如何判断是否新开事务?
@Transactional(propagation = Propagation.REQUIRED,readOnly = true, rollbackFor = Exception.class)
public void updateTest() {
// 执行业务逻辑
}
假设是updateTest是第一层被调用的。
首先,update开头的类名,数据源换到主库。
然后因为@EnableTransactionManager的order是2,优先度较高,所以根据@Transactional先创建readOnly = true的事务。
最后根据方法名update创建事务,因为已经有事务,所以继承,所以还是只读的事务,这个时候执行修改的sql会报错。
that's all

通过AOP切面设置方法拦截器,简单实现通过方法名配置全局事务
浙公网安备 33010602011771号