spring源码学习笔记-初始化(三)-BeanFactory

转自http://www.sandzhang.com/blog/2011/04/05/spring-study-notes-initialization-3/

refresh()方法中在上篇obtainFreshBeanFactory()方法创建了beanfactory对象,之后的代码就开始是对beanFactory对象的一些处理,BeanFactory相关的一些内容也是spring的核心内容。

注:refresh()的代码就不再次列举了,请看spring源码中AbstractApplicationContext类。

一、首先是prepareBeanFactory(beanFactory),主要是做了一些beanFactory的初始化工作,因为这个方法比较长,我们分成4部分来看,

第1部分代码:

  1. beanFactory.setBeanClassLoader(getClassLoader());  
  2. beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());  
  3. beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));  
  4. beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));  
  5. beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);  
  6. beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);  
  7. beanFactory.ignoreDependencyInterface(MessageSourceAware.class);  
  8. beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);  
  9. beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);  
  10. beanFactory.registerResolvableDependency(ResourceLoader.classthis);  
  11. beanFactory.registerResolvableDependency(ApplicationEventPublisher.classthis);  
  12. beanFactory.registerResolvableDependency(ApplicationContext.classthis);  
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver());
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this));
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);


 

  • 第1行设置beanFactory的classLoader为当前context的classLoader
  • 第2行设置beanFactory的表达式语言处理器,spring3增加了表达式语言的支持,默认可以使用#{bean.xxx}的形式来调用相关属性值。
  • 第3行为beanFactory增加了一个默认的propertyEditor,这个主要是对bean的属性等设置管理的一个工具,以后再做详细分析。
  • 第4行添加了一个处理aware相关接口的beanPostProcessor扩展,主要是使用beanPostProcessor的postProcessBeforeInitialization()前置处理方法实现aware相关接口的功能,aware接口是用来给bean注入一些资源的接口,例如实现BeanFactoryAware的Bean在初始化后,Spring容器将会注入BeanFactory的实例相应的还有ApplicationContextAware、ResourceLoaderAware、ServletContextAware等等。
  • 第5-8行设置了几个忽略自动装配的接口,默认只有BeanFactoryAware被忽略,其他的都要自行设置,这里设置了ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware和ApplicationContextAware。
  • 第9-12行设置了几个自动装配的特殊规则,如果是BeanFactory类型,则注入beanFactory对象,如果是ResourceLoader、ApplicationEventPublisher、ApplicationContext类型则注入当前对象(applicationContext对象)。

第2部分代码:

  1. if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {  
  2.     beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));  
  3.     beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));  
  4. }  
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
    beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
    beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}


 

  • 这部分判断是否定义了名为loadTimeWeaver的bean,如果定义了则添加loadTimeWeaver功能的beanPostProcessor扩展,并且创建一个临时的classLoader来让其处理真正的bean。spring的loadTimeWeaver主要是通过 instrumentation 的动态字节码增强在装载期注入依赖。具体这部分还没有很好的理解,暂时标记一下以后再专门研究看看。

第3部分代码:

  1. if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {  
  2.     Map systemProperties;  
  3.     try {  
  4.         systemProperties = System.getProperties();  
  5.     } catch (AccessControlException ex) {  
  6.         systemProperties = new ReadOnlySystemAttributesMap() {  
  7.             protected String getSystemAttribute(String propertyName) {  
  8.                 try {  
  9.                     return System.getProperty(propertyName);  
  10.                 } catch (AccessControlException ex) {  
  11.                     if (logger.isInfoEnabled()) {  
  12.                         logger.info("Not allowed to obtain system property [" + propertyName + "]: " +  
  13.                                 ex.getMessage());  
  14.                     }  
  15.                     return null;  
  16.                 }  
  17.             }  
  18.         };  
  19.     }  
  20.     beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);  
  21. }  
if (!beanFactory.containsBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
    Map systemProperties;
    try {
        systemProperties = System.getProperties();
    } catch (AccessControlException ex) {
        systemProperties = new ReadOnlySystemAttributesMap() {
            protected String getSystemAttribute(String propertyName) {
                try {
                    return System.getProperty(propertyName);
                } catch (AccessControlException ex) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Not allowed to obtain system property [" + propertyName + "]: " +
                                ex.getMessage());
                    }
                    return null;
                }
            }
        };
    }
    beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, systemProperties);
}


这部分首先判断是否定义了名为systemProperties的bean,如果没有则加载系统获取当前系统属性System.getProperties()并注册为一个单例bean。假如有AccessControlException权限异常则创建一个ReadOnlySystemAttributesMap对象,可以看到创建时重写了getSystemAttribute()方法,查看ReadOnlySystemAttributesMap的代码可以得知在调用get方法的时候会去调用这个方法来获取key对应的对象,当获取依旧有权限异常AccessControlException的时候则返回null。

第4部分代码:

  1. if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {  
  2.     Map<String,String> systemEnvironment;  
  3.     try {  
  4.         systemEnvironment = System.getenv();  
  5.     } catch (AccessControlException ex) {  
  6.         systemEnvironment = new ReadOnlySystemAttributesMap() {  
  7.             protected String getSystemAttribute(String variableName) {  
  8.                 try {  
  9.                     return System.getenv(variableName);  
  10.                 } catch (AccessControlException ex) {  
  11.                     if (logger.isInfoEnabled()) {  
  12.                         logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +  
  13.                                 ex.getMessage());  
  14.                     }  
  15.                     return null;  
  16.                 }  
  17.             }  
  18.         };  
  19.     }  
  20.     beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);  
  21. }  
if (!beanFactory.containsBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
    Map<String,String> systemEnvironment;
    try {
        systemEnvironment = System.getenv();
    } catch (AccessControlException ex) {
        systemEnvironment = new ReadOnlySystemAttributesMap() {
            protected String getSystemAttribute(String variableName) {
                try {
                    return System.getenv(variableName);
                } catch (AccessControlException ex) {
                    if (logger.isInfoEnabled()) {
                        logger.info("Not allowed to obtain system environment variable [" + variableName + "]: " +
                                ex.getMessage());
                    }
                    return null;
                }
            }
        };
    }
    beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, systemEnvironment);
}


 

 

  • 这部分和上面一部分类似,只不过由系统属性改为了系统环境变量,异常处理方式等也和上面一部分一样。这两部分都是为spring内部提供系统信息的支撑bean。

 

二、prepareBeanFactory()方法调用之后,是一个try-catch代码块,如果有BeanException异常产生则会停止refresh并且销毁已创建的资源,现在看代码块里的第一行postProcessBeanFactory(beanFactory)

postProcessBeanFactory()方法,默认方法体是空的,主要是用来扩展beanfactory的,扩展点是在bean等配置都已经加载但还没有进行实例化的时候。

例如上面说到的aware相关接口自动装配设置,假如是web项目,使用的是spring的webApplicationcontext,这时需要一些ServletContextAware相关的自动装配忽略及配置等,就需要在webApplicationContext里重写这个方法来实现相应功能。

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值