根据方法名配置全局事务,基于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)一个对象(通常是调用了无参构造方法)的流程

  1. set方法给属性赋值(ref属性)
  2. BeanNameAware 知道自己的名字了
  3. BeanFactoryAware 知道自己由哪个工厂类创建出来
  4. ApplicationContextAware
  5. BeanPostProcessor的before方法
  6. InitializingBean
  7. 自定义的init方法
  8. BeanPostProcessor的after方法
  9. DisposableBean方法
  10. 自定义的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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

LxyrichBos

老板~坐下喝杯茶啊~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值