spring源码学习之路---深入AOP(终)
? ? ? ? ? ? ? ? ?作者:zuoxiaolong8810(左瀟龍),轉(zhuǎn)載請(qǐng)注明出處,特別說明:本博文來自博主原博客,為保證新博客中博文的完整性,特復(fù)制到此留存,如需轉(zhuǎn)載請(qǐng)注明新博客地址即可。
? ? ? ? ? ??? ? 上一章和各位一起看了一下springAOP的工作流程,當(dāng)我們給出AOP相關(guān)的配置以后,直接從IOC容器中拿出來的就是已經(jīng)加強(qiáng)過的bean。這說明spring在這個(gè)過程中一定做了什么。
? ? ? ? ? ? ? ? 本章我們就一起來看一下spring是如何完成對(duì)bean的增強(qiáng)的,首先我們來看一下,FactoryBean接口中一個(gè)方法的定義。
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這個(gè)方法,就是用來獲取被這個(gè)factorybean加強(qiáng)后的對(duì)象的,上一章測(cè)試的過程中,最終就是調(diào)用了這個(gè)方法,來完成了對(duì)bean的加強(qiáng)。我們來跟蹤一下上一次測(cè)試的代碼,看看到底是在什么地方調(diào)用的。這里再次貼出來上次測(cè)試的代碼,方便解釋。
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();}}其實(shí)整個(gè)過程也就兩行代碼,第一行代碼,是我們對(duì)IOC容器的初始化,這時(shí)其實(shí)并沒有發(fā)生對(duì)bean的增強(qiáng),原因就是這個(gè)時(shí)候只是完成了對(duì)ProxyFactoryBean的初始化,也就是相當(dāng)于我們已經(jīng)new出來了一個(gè)ProxyFactoryBean,但是此時(shí)并沒有調(diào)用接口方法,去獲得加強(qiáng)后的bean。
? ? ? ? ?下面我們?nèi)ジM(jìn)第二行獲取testAOP的代碼,來看一下究竟。首先我們會(huì)找到AbstractApplicationContext中的getBean方法,但是這個(gè)類并不負(fù)責(zé)bean的實(shí)例化工作,而是交給了bean工廠,我們跟蹤bean工廠的方法,能找到上述第二行其實(shí)是調(diào)用了如下這個(gè)方法。
@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;}這是一個(gè)重載方法,后面三個(gè)參數(shù)兩個(gè)為null,一個(gè)為false。下面注意,在這面這一行的時(shí)候,我們已經(jīng)獲取到了實(shí)例。
Object sharedInstance = getSingleton(beanName);? ? ? ? ? ? 所以分支在碰到第一個(gè)if判斷時(shí),會(huì)直接進(jìn)入if塊而不是else塊,在這里提醒一下,這個(gè)是獲取的單例的bean實(shí)例,而這個(gè)sharedInstance并不是TestTarget,而是ProxyFactoryBean的實(shí)例。好了,接下來相信你已經(jīng)明白了,我們?cè)撨M(jìn)入getObjectForBeanInstance這個(gè)方法了,來看這個(gè)方法。
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;}方法的剛開始是兩個(gè)衛(wèi)語(yǔ)句,第一個(gè)判斷如果是想獲得factorybean本身,卻又不是factorybean則拋出異常,第二個(gè)則是正常的獲得factorybean。但是我們都不屬于這兩種情況。所以在經(jīng)過getCachedObjectForFactoryBean獲取無果和getCachedObjectForFactoryBean獲取到bean定義以后,就進(jìn)入了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);}}進(jìn)入以后,由于proxyFactorybean是單例bean,所以會(huì)進(jìn)入到if塊不是else塊,接下來系統(tǒng)再次嘗試從cache中獲得,自然是無果。接下來依然會(huì)進(jìn)入到和else一樣的方法doGetObjectFromFactoryBean,先不說這個(gè)方法,看后面,獲得以后就會(huì)放入cache,然后直接將對(duì)象返回。所以如果重復(fù)調(diào)用,下一次就會(huì)從cache當(dāng)中取出來直接返回。好了,接下來我們進(jìn)去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;}此處判斷了一下當(dāng)前是否設(shè)置了安全管理器,我們并沒有設(shè)置,所以將直接調(diào)用ProxyFactoryBean的getObject方法,也就是對(duì)bean增強(qiáng)的地方。下面我們著重來看一下是如何對(duì)bean進(jìn)行增強(qiáng)的。首先我們進(jìn)入到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();}}此處主要是先初始化了一下通知器鏈,然后就會(huì)根據(jù)是否單例做相應(yīng)的動(dòng)作,我們看一下初始化通知器鏈的進(jìn)行。
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;}可以看到,其中針對(duì)我們配置的interpretorNames進(jìn)行了循環(huán),我們并非是配置的全局通知器,所以會(huì)進(jìn)入else塊,然后因?yàn)槲覀兣渲玫膖estAdvisor默認(rèn)是單例的,所以會(huì)從bean工廠中去獲取這個(gè)實(shí)例,此時(shí)TestAdvisor已經(jīng)實(shí)例化完成的,我們只是去取一下而已。然后就會(huì)進(jìn)入addAdvisorOnChainCreation方法。這個(gè)方法不再一一貼進(jìn)來,各位有興趣的可以自己去看一下,就是把通知器加到了通知鏈當(dāng)中。
? ? ? ? ? ? ? 值得注意的是在這個(gè)過程中,觸發(fā)了一個(gè)這樣的方法this.advisorAdapterRegistry.wrap(next)。這個(gè)方法就是用來包裝通知器的,如果不是advisor而是advice,就會(huì)包裝一下返回。
? ? ? ? ? ? ? 好了,接著剛才的過程,初始化通知器鏈完成以后,就會(huì)進(jìn)入getSingletonInstance方法,這是用來獲取單例實(shí)例的,而真正的加強(qiáng)也是在這里發(fā)生的,我們來看一下。
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;}此時(shí)第一次獲取,單例實(shí)例為null,所以會(huì)進(jìn)入if塊,首先刷新targetSource,因?yàn)槲覀兊腡arget類沒有實(shí)現(xiàn)targetSource接口,所以會(huì)由spring幫我們產(chǎn)生一個(gè)targetSource適配,這里是使用的適配器的模式,有興趣可以進(jìn)去看一下,我們此處不關(guān)注這個(gè)。接下來,會(huì)去判斷代理接口,并且設(shè)置代理接口,但是我們的target未實(shí)現(xiàn)任何接口,所以此處interfaces仍然為空的,所以最后一步createAopProxy時(shí),會(huì)幫我們創(chuàng)建cglib的proxy。最終由cglib生成代理返回。
執(zhí)行下國(guó)際慣例,說完以后總要稍微總結(jié)一下,主要說幾點(diǎn):
1.在IOC容器初始化的過程中,并沒有發(fā)生增強(qiáng)的動(dòng)作,而是初始化了proxyFactoryBean。
2.如果配置中不指定,所有bean默認(rèn)都是單例和非延遲加載的,也就是說所有的bean都將在第一次IOC容器初始化時(shí)全部實(shí)例化,所以上一章中所配置的三個(gè)bean都是在IOC容器初始化時(shí)進(jìn)行的實(shí)例化。
3.springAOP代理有兩種方式,一種是JDK提供的動(dòng)態(tài)代理,一種是cglib字節(jié)碼生成的技術(shù),當(dāng)要代理的類有實(shí)現(xiàn)的接口的時(shí)候,就會(huì)針對(duì)接口進(jìn)行代理,否則就會(huì)采用cglib直接生成字節(jié)碼產(chǎn)生子類。
?
? ? ? ? ? ? ? 到此處,我們已經(jīng)基本上完全跟了一遍整個(gè)bean增強(qiáng)的過程,也大概了解了springAOP的大概原理,相信各位心中應(yīng)該有個(gè)大概的印象了,其實(shí)springAOP增強(qiáng)的原理已經(jīng)浮現(xiàn)出來了,接下來再研究下去,可能會(huì)收獲甚微,還是要結(jié)合平時(shí)的應(yīng)用和自己的興趣去體會(huì),始終不贊同一頭扎進(jìn)去就埋頭苦干的作風(fēng)。
? ? ? ? ? ? ? 好了,spring源碼學(xué)習(xí)之路就圓滿結(jié)束了,雖說時(shí)間不長(zhǎng),但收獲甚大。各位如果有興趣,相信現(xiàn)在也完全有能力自己去看源碼了,以后有問題,不要找度娘了,找源碼吧。
?
?
?
?
?
轉(zhuǎn)載于:https://www.cnblogs.com/zuoxiaolong/p/spring7.html
總結(jié)
以上是生活随笔為你收集整理的spring源码学习之路---深入AOP(终)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JSP页面退出时清除会话Session
- 下一篇: 『TCP/IP详解——卷一:协议』读书笔