我的项目中经常会应用到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进行解决。
发表回复