当前位置: 代码迷 >> Web前端 >> Spring Web项目中 ApplicationContext 的获取跟创建Bean的过程1
  详细解决方案

Spring Web项目中 ApplicationContext 的获取跟创建Bean的过程1

热度:1058   发布时间:2013-12-11 16:44:13.0
Spring Web项目中 ApplicationContext 的获取和创建Bean的过程1
?
ApplicationContext ctx =  (ApplicationContext) ContextLoader.getCurrentWebApplicationContext();
TransactionTemplate transactiontemplate =  (TransactionTemplate)ctx.getBean("mes_default_transactionTemplate" );
            
       transactiontemplate.execute( new TransactionCallback() { 
                   @Override
                   public Object doInTransaction(TransactionStatus status) {
                        dataAdapter.delete( "delete from mes_do_used where frompid = #pid#",para);
                        dataAdapter.delete( "delete from mes_daily_turn where frompid = #pid#",para); 
                         return null ;
                  }
            });
?
这段代码是在web项目中获取ApplicationContext对象,然后实例化事务模板 ,用事务管理来删除数据的代码
?
?
  • Web项目里,项目启动的时候ApplicationContext对象就已经建立了,在Web.xml里配置ContexLoaderListener后,启动的时候会执行Listener生成AapplicationContext对象,存储到ServletContext对象中
?
所以在业务代码中,我们需要想办法获取到ApplicationContext对象,然后用这个对象实现工厂模式,返回一个TransactionTemplate实例。
?
我们所需要用到的类 都在org.springframework.web.context这个包下面
?
?
  • 我们访问 抽象类?ContextLoader ?这个类是org.springframework.web.context包里面的抽象类,他有很多静态方法,可以直接用。其中:
 public static WebApplicationContext getCurrentWebApplicationContext() {
   return (WebApplicationContext) currentContextPerThread .get(Thread.currentThread ().getContextClassLoader());
 }
?
这个方法 就可以用来获得WebApplicationContext?对象?WebApplicationContext?对象是继承自ApplicationContext的,可以直接做转换
?
?
??
  • 然后 ? ? ?ctx.getBean("mes_default_transactionTemplate"?);
? ? 这样就从ApplicationContext.xml中的bean配置中 找到了对应的类路径 实例化这个对象
? ? ?getBean 是Spring 的工厂模式 是BeanFactroy接口里的方法 ?这个接口在包
? ? ?org.springframework.beans.factory里面
? ?
我们看看源码:
getBean?(String name) 方法在源码里层层往下找 最后在这里找到org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(String?name,?Class?requiredType,?Object[] args, boolean typeCheckOnly)?
.AbstractBeanFactory这个类里面有实现 叫做doGetBean方法
这个方法里有这一行 ??bean = getObjectForBeanInstance(sharedInstance, name, beanName,?null);
所以还得接着找getObjectForBeanInstanc方法的实现
接着看getObjectForBeanInstanc方法 里面是
object = getCachedObjectForFactoryBean(beanName);这行
?
继续找getCachedObjectForFactoryBean
  • 最后找到了getObjectFromFactoryBean();
?
贴出源代码:
org.springframework.beans.factory.support.FactoryBeanRegistrySupport.getObjectFromFactoryBean(FactoryBean?factory,?String?beanName, boolean shouldPostProcess)
       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);
            }
      }
?
?
factoryBeanObjectCache?是Spring 存放Bean实例对象的集合,Spring建好的对象就都放在这里了。
代码里首先从factoryBeanObjectCache里面去取,去得到就返回,取不到就doGetObjectFromFactoryBean();方法去建立bean对象
然后放到factoryBeanObjectCache里面去 再返回新建的bean对象
?
  • 但是这里doGetObjectFromFactoryBean()还是没有到最终实现,所以要继续往下 到这个方法
org.springframework.beans.factory.support.FactoryBeanRegistrySupport.doGetObjectFromFactoryBean(FactoryBean?factory,?String?beanName, boolean shouldPostProcess)
? ?
private Object doGetObjectFromFactoryBean(
                   final FactoryBean factory, final String beanName, final boolean shouldPostProcess)
                   throws BeanCreationException {
 
            AccessControlContext acc = AccessController. getContext();
             return AccessController.doPrivileged( new PrivilegedAction() {
                   public Object run() {
                        Object object;
 
                         try {
                              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;
                  }
            }, acc);
      }
?
?
可以看到 主要是?object = factory.getObject(); ?
其余的都是获取不到Object时报异常用的代码
?
  • 进一步 看factory.getObject(); ?
org.springframework.beans.factory.config.AbstractFactoryBean.getObject()
public final Object getObject() throws Exception {
             if (isSingleton()) {
                   return (this .initialized ? this. singletonInstance : getEarlySingletonInstance());
            }
             else {
                   return createInstance();
            }
      }
?
?
也是先看是不是单例模式,是的话就判断是不是已经实例化过,如果已经实例化过,就把早先实例化好的对象返回出来
如果不是单例模式 就直接创建新实例?createInstance();
?
  • ?createInstance();再往下本次就不继续看了
?
?
?
?
?
?
? ??
  相关解决方案