乐趣区

关于spring:SpringAop实现入口点简略分析

我的项目中经常会应用到 spring 提供的 aop 技术,那么它的大略实现原理是什么?
省略 spring 扫描 bean 段落,当 spring 扫描完所有的 bean 后,开始对这些 bean 进行实例化和初始化,这样 bean 就筹备好了。
接下来先看创立 bean 办法

protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
               ....
            // 让 BeanPostProcessors 有机会返回一个代理,而不是指标 bean 实例
            Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
            if (bean != null) {return bean;}
            // 否则就去创立这个 bean
            Object beanInstance = doCreateBean(beanName,mbdToUse, args);
            ... 
            return beanInstance;
    }

在下面的办法中,咱们留神到 resolveBeforeInstantiation(),当看到这里的时候,我认为我的项目中的 aop 技术就是在这里使用的,可是理论 debug 下来并不是。

假如咱们有上面的一段代码:

@RestController
public class TestController {

    @MethodLog
    @GetMapping(value = "test")
    public String test(String name) {System.out.println("i come here");
        return "hello";
    }
}

其中 @MethodLog 是一个注解用来标识 AOP,次要目标是在具体方法调用的时候,打印办法的参数。spring 在创立这个 TestController bean 的时候,为什么不在 resolveBeforeInstantiation 返回这个代理对象呢?
这是因为对于 TestController aop 的目标是加强其性能,而不是随便返回一个 TestController 类就行了。
因而必须要先对 TestController 进行实例化,而后对 TestController 进行包装。

上面看 doCreateBean():

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
            throws BeanCreationException {
// 实例化 bean
instanceWrapper = createBeanInstance(beanName, mbd, args);
Object bean = instanceWrapper.getWrappedInstance();
// 填充 bean
populateBean(beanName, mbd, instanceWrapper);
// 初始化 bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
return exposedObject;
}

省略了很多代码,次要剖析要害局部,首先 spring 会抉择结构器实例化一个具体的 bean,而后利用 @value, @Autowired 等注解来进行注入。
最初进行初始化。在实例化和填充阶段都不应该解决代理的逻辑。

上面剖析初始化逻辑

    protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
// 执行初始化之前的办法
if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }
// 执行初始化办法
invokeInitMethods(beanName, wrappedBean, mbd);

// 执行初始化之后的办法
if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
        }

return wrappedBean;
}

当我 debug TestController 创立过程,我发现是从 applyBeanPostProcessorsAfterInitialization()后返回了一个代理对象。
applyBeanPostProcessorsAfterInitialization()理论了是调用了所有的
BeanPostProcessor 的 postProcessAfterInitialization 办法。
在这办法的正文上能够看出,它容许返回一个对象来代替以后对象,或者一个包装器。
在这些 BeanPostProcessor 中,有一个 AbstractAutoProxyCreator,它就是用来产生代理对象的。

上面剖析一下 AbstractAutoProxyCreator 的 postProcessAfterInitialization():

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);
            if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);
            }
        }
        return bean;
    }

外围是调用了 wrapIfNecessary(), 通过这个办法名称也能够看到出就是要判断是否对目标对象进行包装,如果要的话,就返回一个包装后的对象。

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}
        if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}
        if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);
            return bean;
        }

        // 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;
        }

        this.advisedBeans.put(cacheKey, Boolean.FALSE);
        return bean;
    }

在 wrapIfNecessary()中有一句很重要的正文“Create proxy if we have advice.”, 如果咱们对某个类应用了 aop 技术,specificInterceptors 不会空,而后依据这些 specificInterceptors,调用 createProxy()产生一个代理对象。当初大略晓得了 spring aop 实现的初步入口点在哪些地方。

当初回过头来,resolveBeforeInstantiation 到底在什么时候会返回一个代理对象呢?那就是自定义一个 InstantiationAwareBeanPostProcessor, 而后对非凡的 bean 进行解决。

退出移动版