作者:zuoxiaolong8810(左潇龙),转载请注明出处,特别说明:本博文来自博主原博客,为保证新博客中博文的完整性,特复制到此留存,如需转载请注明新博客地址即可。

上一章和各位一起看了一下springAOP的工作流程,当我们给出AOP相关的配置以后,直接从IOC容器中拿出来的就是已经加强过的bean。这说明spring在这个过程中一定做了什么。

本章我们就一起来看一下spring是如何完成对bean的增强的,首先我们来看一下,FactoryBean接口中一个方法的定义。

public interface FactoryBean<T> {

    /**
* Return an instance (possibly shared or independent) of the object
* managed by this factory.
* <p>As with a {@link BeanFactory}, this allows support for both the
* Singleton and Prototype design pattern.
* <p>If this FactoryBean is not fully initialized yet at the time of
* the call (for example because it is involved in a circular reference),
* throw a corresponding {@link FactoryBeanNotInitializedException}.
* <p>As of Spring 2.0, FactoryBeans are allowed to return <code>null</code>
* objects. The factory will consider this as normal value to be used; it
* will not throw a FactoryBeanNotInitializedException in this case anymore.
* FactoryBean implementations are encouraged to throw
* FactoryBeanNotInitializedException themselves now, as appropriate.
* @return an instance of the bean (can be <code>null</code>)
* @throws Exception in case of creation errors
* @see FactoryBeanNotInitializedException
*/
T getObject() throws Exception;

getObject这个方法,就是用来获取被这个factorybean加强后的对象的,上一章测试的过程中,最终就是调用了这个方法,来完成了对bean的加强。我们来跟踪一下上一次测试的代码,看看到底是在什么地方调用的。这里再次贴出来上次测试的代码,方便解释。

public class TestAOP {

    public static void main(String[] args) {
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:beans.xml");
TestTarget target = (TestTarget) applicationContext.getBean("testAOP");
target.test();
System.out.println("------无敌分割线-----");
target.test2();
} }

其实整个过程也就两行代码,第一行代码,是我们对IOC容器的初始化,这时其实并没有发生对bean的增强,原因就是这个时候只是完成了对ProxyFactoryBean的初始化,也就是相当于我们已经new出来了一个ProxyFactoryBean,但是此时并没有调用接口方法,去获得加强后的bean。

下面我们去跟进第二行获取testAOP的代码,来看一下究竟。首先我们会找到AbstractApplicationContext中的getBean方法,但是这个类并不负责bean的实例化工作,而是交给了bean工厂,我们跟踪bean工厂的方法,能找到上述第二行其实是调用了如下这个方法。

@SuppressWarnings("unchecked")
protected <T> T doGetBean(
final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
throws BeansException { final String beanName = transformedBeanName(name);
Object bean; // Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
if (logger.isDebugEnabled()) {
if (isSingletonCurrentlyInCreation(beanName)) {
logger.debug("Returning eagerly cached instance of singleton bean '" + beanName +
"' that is not fully initialized yet - a consequence of a circular reference");
}
else {
logger.debug("Returning cached instance of singleton bean '" + beanName + "'");
}
}
bean = getObjectForBeanInstance(sharedInstance, name, beanName, null);
} else {
// Fail if we're already creating this bean instance:
// We're assumably within a circular reference.
if (isPrototypeCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(beanName);
} // Check if bean definition exists in this factory.
BeanFactory parentBeanFactory = getParentBeanFactory();
if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {
// Not found -> check parent.
String nameToLookup = originalBeanName(name);
if (args != null) {
// Delegation to parent with explicit args.
return (T) parentBeanFactory.getBean(nameToLookup, args);
}
else {
// No args -> delegate to standard getBean method.
return parentBeanFactory.getBean(nameToLookup, requiredType);
}
} if (!typeCheckOnly) {
markBeanAsCreated(beanName);
} final RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);
checkMergedBeanDefinition(mbd, beanName, args); // Guarantee initialization of beans that the current bean depends on.
String[] dependsOn = mbd.getDependsOn();
if (dependsOn != null) {
for (String dependsOnBean : dependsOn) {
getBean(dependsOnBean);
registerDependentBean(dependsOnBean, beanName);
}
} // Create bean instance.
if (mbd.isSingleton()) {
sharedInstance = getSingleton(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
try {
return createBean(beanName, mbd, args);
}
catch (BeansException ex) {
// Explicitly remove instance from singleton cache: It might have been put there
// eagerly by the creation process, to allow for circular reference resolution.
// Also remove any beans that received a temporary reference to the bean.
destroySingleton(beanName);
throw ex;
}
}
});
bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);
} else if (mbd.isPrototype()) {
// It's a prototype -> create a new instance.
Object prototypeInstance = null;
try {
beforePrototypeCreation(beanName);
prototypeInstance = createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
bean = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);
} else {
String scopeName = mbd.getScope();
final Scope scope = this.scopes.get(scopeName);
if (scope == null) {
throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}
try {
Object scopedInstance = scope.get(beanName, new ObjectFactory() {
public Object getObject() throws BeansException {
beforePrototypeCreation(beanName);
try {
return createBean(beanName, mbd, args);
}
finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}
catch (IllegalStateException ex) {
throw new BeanCreationException(beanName,
"Scope '" + scopeName + "' is not active for the current thread; " +
"consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
}
} // Check if required type matches the type of the actual bean instance.
if (requiredType != null && bean != null && !requiredType.isAssignableFrom(bean.getClass())) {
throw new BeanNotOfRequiredTypeException(name, requiredType, bean.getClass());
}
return (T) bean;
}

这是一个重载方法,后面三个参数两个为null,一个为false。下面注意,在这面这一行的时候,我们已经获取到了实例。

Object sharedInstance = getSingleton(beanName);

所以分支在碰到第一个if判断时,会直接进入if块而不是else块,在这里提醒一下,这个是获取的单例的bean实例,而这个sharedInstance并不是TestTarget,而是ProxyFactoryBean的实例。好了,接下来相信你已经明白了,我们该进入getObjectForBeanInstance这个方法了,来看这个方法。

protected Object getObjectForBeanInstance(
Object beanInstance, String name, String beanName, RootBeanDefinition mbd) { // Don't let calling code try to dereference the factory if the bean isn't a factory.
if (BeanFactoryUtils.isFactoryDereference(name) && !(beanInstance instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(transformedBeanName(name), beanInstance.getClass());
} // Now we have the bean instance, which may be a normal bean or a FactoryBean.
// If it's a FactoryBean, we use it to create a bean instance, unless the
// caller actually wants a reference to the factory.
if (!(beanInstance instanceof FactoryBean) || BeanFactoryUtils.isFactoryDereference(name)) {
return beanInstance;
} Object object = null;
if (mbd == null) {
object = getCachedObjectForFactoryBean(beanName);
}
if (object == null) {
// Return bean instance from factory.
FactoryBean factory = (FactoryBean) beanInstance;
// Caches object obtained from FactoryBean if it is a singleton.
if (mbd == null && containsBeanDefinition(beanName)) {
mbd = getMergedLocalBeanDefinition(beanName);
}
boolean synthetic = (mbd != null && mbd.isSynthetic());
object = getObjectFromFactoryBean(factory, beanName, !synthetic);
}
return object;
}

方法的刚开始是两个卫语句,第一个判断如果是想获得factorybean本身,却又不是factorybean则抛出异常,第二个则是正常的获得factorybean。但是我们都不属于这两种情况。所以在经过getCachedObjectForFactoryBean获取无果和getCachedObjectForFactoryBean获取到bean定义以后,就进入了getObjectFromFactoryBean方法。

protected Object getObjectFromFactoryBean(FactoryBean factory, String beanName, boolean shouldPostProcess) {
if (factory.isSingleton() && containsSingleton(beanName)) {
synchronized (getSingletonMutex()) {
Object object = this.factoryBeanObjectCache.get(beanName);
if (object == null) {
object = doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
this.factoryBeanObjectCache.put(beanName, (object != null ? object : NULL_OBJECT));
}
return (object != NULL_OBJECT ? object : null);
}
}
else {
return doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);
}
}

进入以后,由于proxyFactorybean是单例bean,所以会进入到if块不是else块,接下来系统再次尝试从cache中获得,自然是无果。接下来依然会进入到和else一样的方法doGetObjectFromFactoryBean,先不说这个方法,看后面,获得以后就会放入cache,然后直接将对象返回。所以如果重复调用,下一次就会从cache当中取出来直接返回。好了,接下来我们进去doGetObjectFromFactoryBean方法。

private Object doGetObjectFromFactoryBean(
final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
throws BeanCreationException { Object object;
try {
if (System.getSecurityManager() != null) {
AccessControlContext acc = getAccessControlContext();
try {
object = AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
return factory.getObject();
}
}, acc);
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
object = factory.getObject();
}
}
catch (FactoryBeanNotInitializedException ex) {
throw new BeanCurrentlyInCreationException(beanName, ex.toString());
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
} // Do not accept a null value for a FactoryBean that's not fully
// initialized yet: Many FactoryBeans just return null then.
if (object == null && isSingletonCurrentlyInCreation(beanName)) {
throw new BeanCurrentlyInCreationException(
beanName, "FactoryBean which is currently in creation returned null from getObject");
} if (object != null && shouldPostProcess) {
try {
object = postProcessObjectFromFactoryBean(object, beanName);
}
catch (Throwable ex) {
throw new BeanCreationException(beanName, "Post-processing of the FactoryBean's object failed", ex);
}
} return object;
}

此处判断了一下当前是否设置了安全管理器,我们并没有设置,所以将直接调用ProxyFactoryBean的getObject方法,也就是对bean增强的地方。下面我们着重来看一下是如何对bean进行增强的。首先我们进入到ProxyFactoryBean的getObject方法来看一下。

public Object getObject() throws BeansException {
initializeAdvisorChain();
if (isSingleton()) {
return getSingletonInstance();
}
else {
if (this.targetName == null) {
logger.warn("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}

此处主要是先初始化了一下通知器链,然后就会根据是否单例做相应的动作,我们看一下初始化通知器链的进行。

private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
if (this.advisorChainInitialized) {
return;
} if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
} // Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
} // Materialize interceptor chain from bean names.
for (String name : this.interceptorNames) {
if (logger.isTraceEnabled()) {
logger.trace("Configuring advisor or advice '" + name + "'");
} if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisor((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
} else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
addAdvisorOnChainCreation(advice, name);
}
}
} this.advisorChainInitialized = true;
}

可以看到,其中针对我们配置的interpretorNames进行了循环,我们并非是配置的全局通知器,所以会进入else块,然后因为我们配置的testAdvisor默认是单例的,所以会从bean工厂中去获取这个实例,此时TestAdvisor已经实例化完成的,我们只是去取一下而已。然后就会进入addAdvisorOnChainCreation方法。这个方法不再一一贴进来,各位有兴趣的可以自己去看一下,就是把通知器加到了通知链当中。

值得注意的是在这个过程中,触发了一个这样的方法this.advisorAdapterRegistry.wrap(next)。这个方法就是用来包装通知器的,如果不是advisor而是advice,就会包装一下返回。

好了,接着刚才的过程,初始化通知器链完成以后,就会进入getSingletonInstance方法,这是用来获取单例实例的,而真正的加强也是在这里发生的,我们来看一下。

private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
Class targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// Initialize the shared singleton instance.
super.setFrozen(this.freezeProxy);
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}

此时第一次获取,单例实例为null,所以会进入if块,首先刷新targetSource,因为我们的Target类没有实现targetSource接口,所以会由spring帮我们产生一个targetSource适配,这里是使用的适配器的模式,有兴趣可以进去看一下,我们此处不关注这个。接下来,会去判断代理接口,并且设置代理接口,但是我们的target未实现任何接口,所以此处interfaces仍然为空的,所以最后一步createAopProxy时,会帮我们创建cglib的proxy。最终由cglib生成代理返回。

执行下国际惯例,说完以后总要稍微总结一下,主要说几点:

1.在IOC容器初始化的过程中,并没有发生增强的动作,而是初始化了proxyFactoryBean。

2.如果配置中不指定,所有bean默认都是单例和非延迟加载的,也就是说所有的bean都将在第一次IOC容器初始化时全部实例化,所以上一章中所配置的三个bean都是在IOC容器初始化时进行的实例化。

3.springAOP代理有两种方式,一种是JDK提供的动态代理,一种是cglib字节码生成的技术,当要代理的类有实现的接口的时候,就会针对接口进行代理,否则就会采用cglib直接生成字节码产生子类。

到此处,我们已经基本上完全跟了一遍整个bean增强的过程,也大概了解了springAOP的大概原理,相信各位心中应该有个大概的印象了,其实springAOP增强的原理已经浮现出来了,接下来再研究下去,可能会收获甚微,还是要结合平时的应用和自己的兴趣去体会,始终不赞同一头扎进去就埋头苦干的作风。

好了,spring源码学习之路就圆满结束了,虽说时间不长,但收获甚大。各位如果有兴趣,相信现在也完全有能力自己去看源码了,以后有问题,不要找度娘了,找源码吧。

最新文章

  1. python的拷贝(深拷贝和浅拷贝)
  2. Automated Memory Analysis
  3. CentOS 6.8_x64 Oracle 12C 安装
  4. JDBC数据类型
  5. join多表连接和group by分组
  6. 开始编写寄几的 CSS 基础库
  7. 简单Elixir游戏服设计-玩法simple_poker
  8. select into
  9. __x__(7)0905第二天__HTML的发展
  10. svn初涉及使用
  11. 洛谷P1622释放囚犯
  12. 20165303 2017-2017-2《Java程序设计》课程总结
  13. 黄聪:PHP数据库连接失败--could not find driver 解决办法
  14. python基础学习Day11 函数名的应用、闭包、迭代器
  15. 开发者如何更好的选择和适应NoSQL的5个阶段
  16. gulp-connect插件浏览器实时同步刷新
  17. AVFoundation 文本播报
  18. Android 数据库框架GreenDao使用
  19. POJ 3660—— Cow Contest——————【Floyd传递闭包】
  20. git 推送代码到远程端

热门文章

  1. SQL在INNER JOIN时,也可以将子查询加入进来
  2. mysql 如何设置自动增长序列 sequence(一)
  3. Golang gopath
  4. wp8 入门到精通 高仿微信发信息 键盘不消失
  5. phpcms_v9 多图字段 内容页,首页,分页自定义字段调用
  6. 让用VS2012/VS2013编写的程序在XP中顺利运行
  7. 配置ogg异构oracle-mysql(1)基础环境配置
  8. linux中socket的理解
  9. MarkupExtension
  10. android 瀑布流