Spring原始碼學習之路---深入AOP(終)
阿新 • • 發佈:2019-01-18
原文地址:https://blog.csdn.net/zuoxiaolong8810/article/details/8962353
上一章和各位一起看了一下springAOP的工作流程,當我們給出AOP相關的配置以後,直接從IOC容器中拿出來的就是已經加強過的bean。這說明spring在這個過程中一定做了什麼。
本章我們就一起來看一下spring是如何完成對bean的增強的,首先我們來看一下,FactoryBean介面中一個方法的定義。
- publicinterface 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的加強。我們來跟蹤一下上一次測試的程式碼,看看到底是在什麼地方呼叫的。這裡再次貼出來上次測試的程式碼,方便解釋。
- publicclass TestAOP {
- publicstaticvoid main(String[] args) {
- ApplicationContext applicationContext = new FileSystemXmlApplicationContext("classpath:beans.xml");
- TestTarget target = (TestTarget) applicationContext.getBean("testAOP");
- target.test();
- System.out.println("------無敵分割線-----");
- target.test2();
- }
- }
下面我們去跟進第二行獲取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)) {
- thrownew 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);
- }
- elseif (mbd.isPrototype()) {
- // It's a prototype -> create a new instance.
- Object prototypeInstance = null;
- try {
- beforePrototypeCreation(beanName);
- prototypeInstance = createBean(beanName, mbd, args);
- }
- finally {
- afterPrototypeCreation(beanName);
- }