Spring框架注解开发——创建AOP代理对象

AnnotationAwareAsepctJAutoProxyCretor调用的是【InstantiationAwareBeanPostProcessor】后置处理器


作用 1.每个Bean在创建之前都要调用postProcessBeforeInstantiation方法 

 先判断当前Bean是否在advisedBeans中(保存了所有需要增强Bean)需要切面业务逻辑

2.判断当前Bean是不是基础类型的或者是不是有标注@Aspect的切面注解

boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass);

3.是否需要跳过this.shouldSkip(beanClass, beanName))

3.1获取候选的增强器《切面里面的通知方法》

List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
Iterator var4 = candidateAdvisors.iterator();

如果增强器是AspectJPointcutAdvisor类型则会返回true

4.创建对象postProcessAfterInitialization

if (!this.earlyProxyReferences.contains(cacheKey)) {
    return this.wrapIfNecessary(bean, beanName, cacheKey);
}

4.1获取当前Bean的所有增强器(通知方法)specificInterceptors

Object[] specificInterceptors = this.getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, (TargetSource)null);

4.2找到能在当前能应用的增强器(找到哪些方法可以切入到当前Bean的方法)

List<Advisor> candidateAdvisors = this.findCandidateAdvisors();
List<Advisor> eligibleAdvisors = this.findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

有标注过@Before一些切面注解的话,就会被存到eligibleAdvisors 下,当做可以使用的方法

if (!eligibleAdvisors.isEmpty()) {
    eligibleAdvisors = this.sortAdvisors(eligibleAdvisors);
}

在给它们排序一下,毕竟@Before是在前面,假如你顺序不一样,执行的还是@Before 

保存当前Bean在advisedBeans中
this.advisedBeans.put(cacheKey, Boolean.TRUE);

4.3创建代理对象

如果当前Bean需要增强,就需要创建代理对象

4.4获得所有增强器,保存到通知方法proxyFactory 

4.5 创建代理对象 

JdkDynamicAopProxy(Config)jdk动态代理

ObjensisCglibAopProxy(Config)cglib代理

给容器返回到cglib代理对象 

我们可以发现容器中保存了组件的对象(cglib增强后的对象)

5.1然后我们进入到cglib.intercept方法中

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
    Object oldProxy = null;
    boolean setProxyContext = false;
    Class<?> targetClass = null;
    Object target = null;

5.2根据ProxyFactory获取目标方法的拦截器(div)

5.2.1保存所有的拦截器List<Object> interceptorList = new ArrayList(config.getAdvisors().length);

里面有一个默认的增强器,还有四个以@Before,@After,@Returnning,@ReturnningException增强器方法

5.2.2遍历所有的增强器,将其转换成interceptors

5.2.3将增强器转换为List<MethodInterceptor> interceptors

如果是interceptors则直接添加到

if (advice instanceof MethodInterceptor) {

interceptors.add((MethodInterceptor)advice); }

如果不是interceptors则先创建一个迭代器

Iterator var4 = this.adapters.iterator();

while(var4.hasNext()) {
    AdvisorAdapter adapter = (AdvisorAdapter)var4.next();
    if (adapter.supportsAdvice(advice)) {
        interceptors.add(adapter.getInterceptor(advisor));
    }

转换完成返回

return (MethodInterceptor[])interceptors.toArray(new MethodInterceptor[interceptors.size()]);

我们发现AfterReturnning和Before都被封装过

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

 5.3如果没有拦截器链,直接执行目标方法

拦截器链(每一个方法都被包装成拦截器。利用MethodInterceptor机制)

如果有拦截器链,把需要执行的目标对象,目标方法,拦截器链所有信息创建一CglibMethodInvocation对象并调用proceed方法

retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();

5.4拦截器链的触发过程

retVal = (new CglibAopProxy.CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy)).proceed();

我们将转换完成的方法,执行new CglibAopProxy.proceed方法

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return this.invokeJoinpoint();

currentInterceptorIndex记录当前拦截器的索引

5.1如果没有执行拦截器目标方法,或者拦截器的索引和拦截器数组大小-1相同

5.2 通过 else { Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

++导致每次索引会多一,会遍历完所有拦截器

六——拦截器调用所有通知 

当我们的拦截器通知达到5的时候 ,立马会调用我们的前置通知

当索引和拦截器一样长的时候则会进入invokeJoinpoint方法

if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
    return this.invokeJoinpoint();

这里的做法就是数据结构的压栈(栈的插入)根据先进后出的方法,依次调用倒数第二个进,倒数第三个进,最后得出所有方法

 具体流程图如下

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值