spring的BeanFactory和ApplicationContext源码详解(二)

2011-05-11 21:15:04 by sand, 745 visits, Tags: BeanFactory, Spring, ApplicationContext, Java,

版本:spring-framework-3.0.5.RELEASE

接上篇继续

一、首先看ConfigurableBeanFactory接口

本接口继承了HierarchicalBeanFactory和SingletonBeanRegistry,接口代码如下:

String SCOPE_SINGLETON = "singleton";
String SCOPE_PROTOTYPE = "prototype";

void setParentBeanFactory(BeanFactory parentBeanFactory) throws IllegalStateException;

void setBeanClassLoader(ClassLoader beanClassLoader);
ClassLoader getBeanClassLoader();

void setTempClassLoader(ClassLoader tempClassLoader);
ClassLoader getTempClassLoader();

void setCacheBeanMetadata(boolean cacheBeanMetadata);
boolean isCacheBeanMetadata();

void setBeanExpressionResolver(BeanExpressionResolver resolver);
BeanExpressionResolver getBeanExpressionResolver();

void setConversionService(ConversionService conversionService);
ConversionService getConversionService();

void addPropertyEditorRegistrar(PropertyEditorRegistrar registrar);

void registerCustomEditor(Class requiredType, Class<? extends PropertyEditor> propertyEditorClass);

void copyRegisteredEditorsTo(PropertyEditorRegistry registry);

void setTypeConverter(TypeConverter typeConverter);
TypeConverter getTypeConverter();

void addEmbeddedValueResolver(StringValueResolver valueResolver);
String resolveEmbeddedValue(String value);

void addBeanPostProcessor(BeanPostProcessor beanPostProcessor);
int getBeanPostProcessorCount();

void registerScope(String scopeName, Scope scope);
String[] getRegisteredScopeNames();
Scope getRegisteredScope(String scopeName);

AccessControlContext getAccessControlContext();

void copyConfigurationFrom(ConfigurableBeanFactory otherFactory);

void registerAlias(String beanName, String alias) throws BeanDefinitionStoreException;
void resolveAliases(StringValueResolver valueResolver);

BeanDefinition getMergedBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

boolean isFactoryBean(String name) throws NoSuchBeanDefinitionException;

boolean isCurrentlyInCreation(String beanName);

void registerDependentBean(String beanName, String dependentBeanName);

String[] getDependentBeans(String beanName);
String[] getDependenciesForBean(String beanName);

void destroyBean(String beanName, Object beanInstance);
void destroyScopedBean(String beanName);
void destroySingletons();
  • 前面两行是定义了spring里bean的两个作用域名称:singleton和prototype,基本两个的区别就是一为单例模式的一个对象,spring对其生命周期负责;二为每次请求都会生成新的对象,spring只负责创建,并不负责其生命周期管理。具体的作用域相关详细分析请查看  spring作用域分析
  • 第4行设置ParentBeanFactory
  • 第6-19行是标准的Javabean模板的Getter/Setter方法了,分别是对beanClassLoader(类加载器),tempClassLoader(临时加载器),cacheBeanMetadata(是否缓存bean的元数据),BeanExpressionResolver(表达式语言处理器),conversionService(数据转换服务)的操作
  • 第21行为添加bean属性编辑器的管理器
  • 第23行注册某个类型requiredType的属性编辑器为propertyEditorClass
  • 第25行将所有当前已经注册的属性编辑器类型初始化并注册到输入参数registry中
  • 第27-28行是typeConverter的Getter/Setter方法,这个对象是bean属性的转换器,会覆盖propertyEditor机制
  • 第30行添加字符串解析器,主要用于嵌入式的属性解析,例如注解中的属性
  • 第31行进行字符串属性解析,使用的就是上面添加的字符串解析器
  • 第33行注册一个BeanPostProcessor
  • 第34行获取已经注册的BeanPostProcessor的数量
  • 第36-38行分别为注册bean的作用域,获取所有作用域名称,根据名称获取作用域对象
  • 第40行获取安全管理上下文对象
  • 第42行从传入的otherFactory中获取所有配置信息(BeanPostProcessors,作用域等),但不包括具体的bean定义信息
  • 第44行注册bean别名
  • 第45行是使用传入的valueResolver对别名进行处理
  • 第47行根据beanName获取bean定义信息对象
  • 第49行判断指定name的bean是否为FactoryBean
  • 第51行判断指定name的bean是否正在创建中
  • 第53行注册dependentBeanName为beanName的依赖bean,在销毁beanName对应的bean之前必须要先销毁dependentBeanName对应的bean
  • 第55-56行获取所有依赖于beanName的bean名称,以及获取所有beanName依赖的bean名称。
  • 第58行销毁bean实例
  • 第59行把bean从其作用域中移除并销毁
  • 第60行销毁所有单例bean

 

二、ConfigurableListableBeanFactory接口

本接口继承了ListableBeanFactory, AutowireCapableBeanFactory, ConfigurableBeanFactory,代码如下:

void ignoreDependencyType(Class type);
void ignoreDependencyInterface(Class ifc);

void registerResolvableDependency(Class dependencyType, Object autowiredValue);

boolean isAutowireCandidate(String beanName, DependencyDescriptor descriptor)
        throws NoSuchBeanDefinitionException;

BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException;

void freezeConfiguration();
boolean isConfigurationFrozen();

void preInstantiateSingletons() throws BeansException;
  • 第1行忽略指定类型的自动装配,默认为空
  • 第2行忽略指定接口的自动装配,默认只忽略BeanFactoryAware接口
  • 第4行这个还没有弄清楚,弄清楚了再补上……
  • 第6行判断bean的依赖是否自动装配
  • 第9行根据beanname获取bean的定义信息对象
  • 第11行第锁住所有bean定义信息,锁住后将不允许对其修改
  • 第12行判断bean定义对象是否被锁住
  • 最后一行是确保对所有非延迟加载的单例bean进行初始化,也就是说在这里会对所有没有初始化的非延迟加载单例bean进行初始化。

 

三、ApplicationContext接口

本接口继承了ListableBeanFactory, HierarchicalBeanFactory,MessageSource, ApplicationEventPublisher, ResourcePatternResolver,其中ListableBeanFactory是bean相关的列表功能,HierarchicalBeanFactory代表了它本身有层级支持,MessageSource代表了spring的国际化信息支撑,ApplicationEventPublisher代表了spring的事件处理支撑,ResourcePatternResolver则是资源处理相关的支撑。接口代码如下:

String getId();

String getDisplayName();

long getStartupDate();

ApplicationContext getParent();

AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException;
  • 这个代码就很简单了,基本上的功能都是在几个父接口里,特殊的地方就是多几个属性id,displayName,startupDate,parentApplicationContext,autowireCapableBeanFactory的get或set方法

这里简单说下ApplicationContext虽然它是BeanFactory的子接口,但是可以认为它不是一个BeanFactory,ApplicationContext对象里面包含了一个BeanFactory对象,相关bean基本功能是调用了其内部的一个BeanFactory对象来实现的,而不是自己进行的实现,它对BeanFactory进行了一定的封装扩展,另外国际化支持,事件监听等都集成在了里面。

评论 (2)        

spring的BeanFactory和ApplicationContext源码详解(一)

2011-04-10 11:46:41 by sand, 966 visits, Tags: BeanFactory, Spring, ApplicationContext, Java,

版本:spring-framework-3.0.5.RELEASE

Spring的最核心的部分就是BeanFactory了,当然我们现在很少直接使用这个类而是通过ApplicationContext来使用了,本篇我们就对BeanFactory接口的核心方法、BeanFactory的子接口及其实现类以及ApplicationContext相关做一个详细的分析和了解。关于实现代码牵扯到的东西太多了,这里只分析接口的功能及继承关系,暂时不做实现类的分析。

一、我们首先看下BeanFactory接口的代码:

public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";

    Object getBean(String name) throws BeansException;
    <T> T getBean(String name, Class<T> requiredType) throws BeansException;
    <T> T getBean(Class<T> requiredType) throws BeansException;
    Object getBean(String name, Object... args) throws BeansException;

    boolean containsBean(String name);
    boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
    boolean isPrototype(String name) throws NoSuchBeanDefinitionException;
    boolean isTypeMatch(String name, Class targetType) throws NoSuchBeanDefinitionException;

    Class<?> getType(String name) throws NoSuchBeanDefinitionException;
    String[] getAliases(String name);
}
  1. 首先第2行是一个字符串常量,值为"&",这个是用在FactoryBean那部分,假如有一个FactoryBean的name=foo,则使用name=&foo去取bean对象的时候取到的就是foo的工厂而不是foo本身。
  2. 第4行根据bean的name去查找bean,在当前BeanFactory查找不到的时候会去查找parent的BeanFactory,返回为一个Object对象需用户自行转换其原本的类型。
  3. 第5行也是根据name查找bean,但是多了一个参数requiredType,查找bean并要求结果符合这个类型,如果requiredType为null,则同上个方法一样只根据name查找,另外这里使用了泛型,返回对象类型会直接是requiredType。
  4. 第6行是根据requiredType查找bean,查找一个符合这个类型的bean,同样返回类型为requiredType。
  5. 第7行根据name查找bean,同时有一个参数组args,这个主要是用来给给工厂类创建bean对象的时候调用的,所以如果args不为空则意味着这里查找的是一个prototype的bean。
  6. 第9-12行分别是几个判断方法:判断是否存在bean;是否是单例bean;是否是prototype的bean,bean是否符合类型requiredType。
  7. 第13行是根据bean的name获取bean的类型。
  8. 最后是根据bean的name获取指向该bean的所有别名,如果输入的name本身就是别名,那返回的将包括bean的最初name,并且这个name在返回的数组中第一个元素。
     

二、现在我们看下BeanFactory的子接口

BeanFactory一共有3个子接口一个实现类,其中实现类SimpleJndiBeanFactory主要是jndi相关,我们这里暂不讨论,下面看3个接口

2.1、HierarchicalBeanFactory接口:主要定义BeanFactory的分层的支撑,所谓分层也就是parentBeanFactory概念

2.1.1、首先看下代码:

public interface HierarchicalBeanFactory extends BeanFactory {
    BeanFactory getParentBeanFactory();
    boolean containsLocalBean(String name);
}
  1. getParentBeanFactory()方法获取parentBeanFactory;
  2. containsLocalBean()则类似containsBean()只不过这个方法只在当前BeanFactory查找bean,如果没有不再去parent里查找了。
     

2.1.2、这个接口有两个子接口:ApplicationContext和ConfigurableBeanFactory,关于这两个子接口下面独立做分析,因为他们已经不只是HierarchicalBeanFactory的子接口了。

 

2.2、ListableBeanFactory接口:主要是获取bean的定义和配置信息相关的支撑接口

2.2.1、代码如下:

public interface ListableBeanFactory extends BeanFactory {
    boolean containsBeanDefinition(String beanName);
    int getBeanDefinitionCount();
    String[] getBeanDefinitionNames();
    String[] getBeanNamesForType(Class type);
    String[] getBeanNamesForType(Class type, boolean includeNonSingletons, boolean allowEagerInit);
    <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException;
    <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
            throws BeansException;
    Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
            throws BeansException;
    <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType);
}
  • containsBeanDefinition()方法判断是否存在指定beanName的定义信息
  • getBeanDefinitionCount()获取bean定义的总数
  • getBeanDefinitionNames()获取所有bean定义的name数组
  • getBeanNamesForType()获取所有指定类型的bean的name数组
  • 第2个getBeanNamesForType()方法多了两个餐厨,可以指定是否单例,是否渴望初始化
  • 两个getBeansOfType()和getBeanNamesForType()的参数一样,只不过这个返回的是name为key,bean对象为value的map集合
  • getBeansWithAnnotation()方法获取包含指定注解annotationType所有bean的map集合
  • 最后findAnnotationOnBean()方法获取指定beanName的指定注解的注解信息对象
     

2.1.2、这个接口有两个子接口:ApplicationContext和ConfigurableListableBeanFactory,关于这两个子接口同样放到下面独立做分析。

注:该接口还有一个静态实现类StaticListableBeanFactory,没发现哪里在使用,代码上也很简单就是把bean的定义放到一个map集合beans里面,实现一个基本的本接口功能,暂不做分析。
 

2.3、AutowireCapableBeanFactory接口:主要是spring的自动装配相关功能支撑接口

2.3.1、代码如下:

public interface AutowireCapableBeanFactory extends BeanFactory {
    int AUTOWIRE_NO = 0;
    int AUTOWIRE_BY_NAME = 1;
    int AUTOWIRE_BY_TYPE = 2;
    int AUTOWIRE_CONSTRUCTOR = 3;
    int AUTOWIRE_AUTODETECT = 4;

    <T> T createBean(Class<T> beanClass) throws BeansException;
    Object createBean(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;

    Object configureBean(Object existingBean, String beanName) throws BeansException;
    Object initializeBean(Object existingBean, String beanName) throws BeansException;
    Object autowire(Class beanClass, int autowireMode, boolean dependencyCheck) throws BeansException;
    void autowireBean(Object existingBean) throws BeansException;
    void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck)
            throws BeansException;
    void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException;
    Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
            throws BeansException;
    Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
            throws BeansException;
    Object resolveDependency(DependencyDescriptor descriptor, String beanName) throws BeansException;
    Object resolveDependency(DependencyDescriptor descriptor, String beanName,
            Set<String> autowiredBeanNames, TypeConverter typeConverter) throws BeansException;
}

这个接口的主要实现代码都在AbstractAutowireCapableBeanFactory类中,暂时也没有发现其他地方用到这个接口,查看这些方法的实现可以去看这个类。

  • 首先是5个常量代表自动装配的类型:不自动装配、按name、按类型、根据自省完全自动装配(不推荐,已在3.0中过时)。
  • 两个创建Bean的方法,一个是根据类型,另外一个多了两个参数自动装配类型和是否检查依赖
  • configureBean()是一个用来主动的配置装配的,就是在需要的时候把existingBean自动装配给beanName对应的bean
  • initializeBean()是bean的初始化方法在这里主要调用了几个工厂级回调(BeanNameAware、BeanClassLoaderAware和BeanFactoryAware),并处理了所有BeanPostProcessor的两个调用
  • autowire()方法创建一个类型为beanClass的bean对象,并根据自动装配类型autowireMode进行自动装配,dependencyCheck则代表是否做依赖检查
  • autowireBean()方法暂时没有很清楚,只知道和普通的按name按类型装配不同,和注解相关,以后分析清楚了再补充。
  • autowireBeanProperties方法()和上面的方法类似,只不过省略了bean创建的步骤,直接穿入一个bean对象进行自动装配
  • applyBeanPropertyValues()应用bean定义中明确定义的属性值,区别于autowireBeanProperties(会装配所有属性)。
  • applyBeanPostProcessorsBeforeInitialization()和applyBeanPostProcessorsAfterInitialization()两个方法处理BeanPostProcessor的两种回调,上面的initializeBean()方法的实现中就是调用这两个
  • 两个resolveDependency()方法也没有搞清楚,是跟bean的依赖相关的,以后清楚了再补充。

2.3.2、这个接口的继承结构也很清晰,一个子接口ConfigurableListableBeanFactory,一个实现类AbstractAutowireCapableBeanFactory。

下一篇:ConfigurableBeanFactory、ConfigurableListableBeanFactory、ApplicationContext

评论 (1)        

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

2011-04-05 10:21:17 by sand, 884 visits, Tags: BeanFactory, Spring, Java,

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

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

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

第1部分代码:

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部分代码:

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部分代码:

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部分代码:

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里重写这个方法来实现相应功能。

评论 (1)        

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

2011-04-02 20:59:07 by sand, 684 visits, Tags: Spring, BeanFactory, Java,

上篇结束的地方简单介绍了一下refresh()方法,现在我们具体分析一下它的代码细节:

1.首先可以看到整个refresh()的代码都是同步的,对应的同步对象是startupShutdownMonitor,我们看一下startupShutdownMonitor引用的地方,可以知道,只有在refresh()和close()两个方法里用到,说明这个锁是用来同步applicationContext的刷新和销毁的。

2.同步代码块的第一行是prepareRefresh()方法,代码如下:

protected void prepareRefresh() {
    this.startupDate = System.currentTimeMillis();
    synchronized (this.activeMonitor) {
        this.active = true;
    }
    if (logger.isInfoEnabled()) {
        logger.info("Refreshing " + this);
    }
}

这个方法也很简单

  1. 首先设置startupDate为系统当前毫秒数,代表当前applicationContext的创建时间;
  2. 设置active为true,代表当前applicationContext是活动的,可以看到对active的赋值操作是同步的,同步对象为activeMonitor,查看active的引用点,可以看到所有对 active的操作都是同步在activeMonitor下的,在调用cancelRefresh()和doClose()两个方法的时候会把它设置为false,其中cancelRefresh()代表中止refresh,doClose()则是当前applicationContext的关闭销毁方法
  3. 最后是日志的打印,info级别,我这里要说的一点是后面直接+this,代表会调用toString方法,AbstractApplicationContext重写了toString,大概格式是displayName+startup+parent displayName

3.接着是这一行:ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(),obtainFreshBeanFactory代码如下:

protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
    }
    return beanFactory;
}

第一行调用refreshBeanFactory(),我们先跳过这行看下面,调用了getBeanFactory()获得beanFactory对象然后返回这个对象,看getBeanFactory()的代码可以看到,是做了一个同步,然后取出当前对象里的beanFactory,同步锁是beanFactoryMonitor:

注:refreshBeanFactory()和getBeanFactory()方法在AbstractRefreshableApplicationContext类里面,关于ApplicationContext的类结构我会在另外一篇文章里做专门介绍,请看:ApplicationContext的类继承结构及框架图

public final ConfigurableListableBeanFactory getBeanFactory() {
    synchronized (this.beanFactoryMonitor) {
        if (this.beanFactory == null) {
            throw new IllegalStateException("BeanFactory not initialized or already closed - " +
                    "call 'refresh' before accessing beans via the ApplicationContext");
        }
        return this.beanFactory;
    }
}

如果beanFactory为空则会抛出异常,其实一开始beanFactory肯定是null的,beanFactory的创建就是在refreshBeanFactory()方法中,下面我们看它的代码:

protected final void refreshBeanFactory() throws BeansException {
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        customizeBeanFactory(beanFactory);
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
    }
}

前面3行代码首先判断是否hasBeanFactory(),如果存在则调用destroyBeans()以及closeBeanFactory():

  • hasBeanFactory()是在判断属性beanFactory是否为空,当然同上面一样beanFactory的操作是同步的,同步对象是beanFactoryMonitor。
  • destroyBeans()方法只有一行代码:getBeanFactory().destroySingletons(),调用了beanFactory对象的destroySingletons()方法来销毁所有单例bean。(后面还会用到这个方法,放到后面详细介绍)
  • closeBeanFactory()和上面一样,依旧是同步的情况下处理beanFactory属性,首先调用setSerializationId(null),然后把beanFactory属性设置为null。

接下来后面的代码是一个创建beanFactory的过程:

  • 调用createBeanFactory()方法创建一个beanFactory对象:
    查看方法代码可以看到创建的是一个DefaultListableBeanFactory对象,参数parent传递的方法getInternalParentBeanFactory()返回的结果,getInternalParentBeanFactory()方法的代码为:
    (getParent() instanceof ConfigurableApplicationContext) ? ((ConfigurableApplicationContext) getParent()).getBeanFactory() : getParent()
    如果当前applicationContext对象的parent是ConfigurableApplicationContext类的实例则返回当前对象的parent的beanFactory对象,否则直接返回当前对象的parent。
     
  • 将当前对象的id属性作为参数调用为beanFactory对象的setSerializationId()方法,我们这里看下这个方法的代码:
    public void setSerializationId(String serializationId) {
        if (serializationId != null) {
            serializableFactories.put(serializationId,
                    new WeakReference<DefaultListableBeanFactory>(this));
        } else if (this.serializationId != null) {
            serializableFactories.remove(this.serializationId);
        }
        this.serializationId = serializationId;
    }
    首先,输入参数如果不为空执行(1),否则再判断如果当前对象的属性serializationId不为空,执行(2)
    (1)在serializableFactories里加入一组值:键为serializationId,值为当前对象的弱引用
    (2)从serializableFactories中移除键为当前对象属性serializationId的对象,也就是以前存入的当前对象的弱引用
    (3)设置属性serializationId为输入参数
     
  • customizeBeanFactory()方法的代码:
    protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
        if (this.allowBeanDefinitionOverriding != null) {
            beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
        }
        if (this.allowCircularReferences != null) {
            beanFactory.setAllowCircularReferences(this.allowCircularReferences);
        }
        beanFactory.setParameterNameDiscoverer(new LocalVariableTableParameterNameDiscoverer());
        beanFactory.setAutowireCandidateResolver(new QualifierAnnotationAutowireCandidateResolver());
    }
    如果属性allowBeanDefinitionOverriding不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许覆盖同名称的不同定义的对象
    如果属性allowCircularReferences不为空,设置给beanFactory对象相应属性,此属性的含义:是否允许bean之间循环引用
    设置beanFactory的parameterNameDiscoverer属性为一个新的LocalVariableTableParameterNameDiscoverer对象,主要用asm解析class文件
    设置beanFactory的parameterNameDiscoverer属性为一个新的QualifierAnnotationAutowireCandidateResolver对象,主要用于自动装配的处理
     
  • loadBeanDefinitions()方法的代码:
    protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setResourceLoader(this);
        beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }
    第1行创建XmlBeanDefinitionReader对象
    第2行设置beanDefinitionReader的resourceLoader属性为当前对象
    第3行设置beanDefinitionReader的entityResolver属性为一个新的ResourceEntityResolver对象,输入参数resourceLoader为当前对象,这个数要是用来解析xml的
    第4行设置beanDefinitionReader的validationMode以及namespaceAware,参数是当前对象的validating属性,主要用于xml校检
    最后一行是做了xml配置文件的读取,就不做详细描述了,有个细节是会循环加载configResources、configLocations两个里面的文件
     
  • 接着是同步操作beanFactory,把创建的beanFactory对象赋值给当前ApplicationContext的beanFactory属性

评论 (2)