http://www.aichengxu.com/view/45222
BeanFactory和ApplicationContext都可以用来作为Bean工厂负责创建和管理Bean,相比之下ApplicationContext是BeanFactory的一个增强升级版,比如ApplicationContext提供了强大的事件机制,自动加载BeanPostProcessor(BPP)和BeanFactoryPostProcessor(BFPP),预创建Bean等,一般情况下都使用ApplicationContext来当作Bean工厂,除非某些对内存有严格要求的应用才会考虑使用BeanFactory,下面从源码入手基于ApplicationContext分析bean工厂的启动过程,ApplicationContext有FileSystemXmlApplicationContext、ClassPathXmlApplicationContext等实现,下面通过ClassPathXmlApplicationContext来进行分析。Spring的代码风格非常好,结构非常清晰便于阅读,基本上从方法名上就能猜出来这个方法的功能,从refresh这个方法就基本上能看出来容器在启动时做了哪些事情。这点非常值得我们学习,要写出高质量的代码多看看牛人的代码是非常有必要的。下面是容器启动的核心代码,反应了容器启动的核心步骤。
org.springframework.context.support.ClassPathXmlApplicationContext.ClassPathXmlApplicationContext(String[], boolean, ApplicationContext)
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException { super(parent); setConfigLocations(configLocations); if (refresh) { refresh(); } } org.springframework.context.support.AbstractApplicationContext.refresh() public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // Prepare this context for refreshing.处理配置文件中的占位符 prepareRefresh(); // Tell the subclass to refresh the internal bean factory.
初始化一个默认的bean factoryDefaultListableBeanFactory,这个bean factory还只是一个空架子,组件容器都是空的(Map),还没有组件()org.springframework.beans.factory.support.DefaultListableBeanFactory实例变量:
/** Resolver to use for checking if a bean definition is an autowire candidate */
private AutowireCandidateResolver autowireCandidateResolver = new SimpleAutowireCandidateResolver();
/** Map from dependency type to corresponding autowired value */
private final Map<Class<?>, Object> resolvableDependencies = new HashMap<Class<?>, Object>(16);
/** Map of bean definition objects, keyed by bean name */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>(64);
/** Map of singleton and non-singleton bean names, keyed by dependency type */
private final Map<Class<?>, String[]> allBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
/** Map of singleton-only bean names, keyed by dependency type */
private final Map<Class<?>, String[]> singletonBeanNamesByType = new ConcurrentHashMap<Class<?>, String[]>(64);
/** List of bean definition names, in registration order */
private final List<String> beanDefinitionNames = new ArrayList<String>(64);
/** List of names of manually registered singletons, in registration order */
private final Set<String> manualSingletonNames = new LinkedHashSet<String>(16);
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); // Prepare the bean factory for use in this context.给DefaultListableBeanFactory的组件容器,放入默认的组件。 prepareBeanFactory(beanFactory); try { // Allows post-processing of the bean factory in context subclasses. postProcessBeanFactory(beanFactory); // Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(beanFactory); // Register bean processors that intercept bean creation. registerBeanPostProcessors(beanFactory); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate all remaining (non-lazy-init) singletons. finishBeanFactoryInitialization(beanFactory); // Last step: publish corresponding event. finishRefresh(); } catch (BeansException ex) { // Destroy already created singletons to avoid dangling resources. destroyBeans(); // Reset 'active' flag. cancelRefresh(ex); // Propagate exception to caller. throw ex; } } }Sring容器在初始化的时候主要会做下面这些事情:
1、合并父容器的环境信息(Environment)
2、设置bean配置文件路径到容器中,如果路径中有占位符,替换占位符为真实路径
如下面的例子,路径中就包含了占位符, 占位符和路径对应关系存在System变量中,也可以使用环境变量中的value System.getenv()。
System.setProperty("config_folder", "spring/beans/test"); System.setProperty("config_file", "beans.xml"); BeanFactory context = new ClassPathXmlApplicationContext("${config_folder}/${config_file}");System、环境变量等key-value对封装到org.springframework.core.env.PropertySource类,下面代码把这些key-value封装进PropertySource,org.springframework.core.env.StandardEnvironment类中的代码。
protected void customizePropertySources(MutablePropertySources propertySources) { propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties())); propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment())); }下面是提取占位符代码,在org.springframework.util.PropertyPlaceholderHelper类中
protected String parseStringValue( String strVal, PlaceholderResolver placeholderResolver, Set<String> visitedPlaceholders) { StringBuilder buf = new StringBuilder(strVal); int startIndex = strVal.indexOf(this.placeholderPrefix); while (startIndex != -1) { int endIndex = findPlaceholderEndIndex(buf, startIndex); if (endIndex != -1) { String placeholder = buf.substring(startIndex + this.placeholderPrefix.length(), endIndex); ... } else { startIndex = -1; } } return buf.toString(); }提取出占位符之后从PropertySource中读取占位符对应的值,代码在org.springframework.core.env.PropertySourcesPropertyResolver类中。读取出来的值就是最终的Bean配置文件路径,容器根据这个路径加载配置文件
protected <T> T getProperty(String key, Class<T> targetValueType, boolean resolveNestedPlaceholders) { ... if (this.propertySources != null) { for (PropertySource<?> propertySource : this.propertySources) { if (debugEnabled) { logger.debug(String.format("Searching for key '%s' in [%s]", key, propertySource.getName())); } Object value; if ((value = propertySource.getProperty(key)) != null) { ... return this.conversionService.convert(value, targetValueType); } } } ... return null; }
3、准备刷新容器,校验坏境中的必须设置属性是否已经被设置
4、创建Bean工厂,ClassPathXmlApplicationContext不会加载和创建Bean,而是把这些工作代理给DefaultListableBeanFactory,这一步把这个bean工厂创建并且初始化
初始化Bean工厂要进行如下步骤
4.1、判断当前是否存在Bean工厂,如果已经存在,删除老Bean工厂注册的单例bean,关闭bean工厂,清除bean工厂的序列化id,清空beanFactory引用
4.2、创建bean工厂DefaultListableBeanFactory实例
4.3、设置bean工厂的序列化id,序列化id的默认格式是:ApplicationContext类权限名@ApplicationContext实例hashcode十六进制
序列化id是用来辅助Bean工厂序列化的,相关代码如下,因为DefaultListableBeanFactory是一个比较大的对象,里面包含了不少的字段,其中还有一些类型没有实现Serializable接口的字段,比如autowireCandidateResolver字段,所以无法直接对DefaultListableBeanFactory进行序列化,就算是把这种字段修饰成transient,序列化DefaultListableBeanFactory对象也是个比较好CPU的动作,所以经过如下处理,通过全局存储DefaultListableBeanFactory弱引用(不妨碍GC)和序列化id的映射关系,序列化时只需存储序列化id,反序列化时通过id查找DefaultListableBeanFactory实例。这样可以提高序列化效率。关于writeReplace和readResolve的用法可以直接问度娘。
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; } protected Object writeReplace() throws ObjectStreamException { if (this.serializationId != null) { return new SerializedBeanFactoryReference(this.serializationId); } else { throw new NotSerializableException("DefaultListableBeanFactory has no serialization id"); } } private static class SerializedBeanFactoryReference implements Serializable { private final String id; public SerializedBeanFactoryReference(String id) { this.id = id; } private Object readResolve() { Reference<?> ref = serializableFactories.get(this.id); if (ref == null) { throw new IllegalStateException( "Cannot deserialize BeanFactory with id " + this.id + ": no factory registered for this id"); } Object result = ref.get(); if (result == null) { throw new IllegalStateException( "Cannot deserialize BeanFactory with id " + this.id + ": factory has been garbage-collected"); } return result; } }4.4、设置allowBeanDefinitionOverriding属性,是否允许覆盖bean定义,这个属性决定了配置文件中是否可以定义同名的bean,如果不允许的话容器会抛出BeanDefinitionStoreException异常,代码处理在DefaultListableBeanFactory的registerBeanDefinition方法。
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException { ... Object oldBeanDefinition = this.beanDefinitionMap.get(beanName); if (oldBeanDefinition != null) { if (!this.allowBeanDefinitionOverriding) { throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName, "Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName + "': There is already [" + oldBeanDefinition + "] bound."); } } ... }4.5、设置allowCircularReferences属性,是否允许循环引用,默认是true允许,可以通过扩展ApplicationContext把它设置成false。
关于创建bean时的循环引用处理,在创建之前先判断bean的名称是否已经存在singletonsCurrentlyInCreation哈希表属性中,如果已经在这个哈希表中,说明这个bean正在创建,发生了循环引用在填充属性的时候又让回来了,这时候需要判断是否允许循环引用,如果允许的话提前暴露该bean的引用。在创建bean之前把bean的名称放到哈希表中,创建完成之后把它从哈希表中删除。
DefaultSingletonBeanRegistry
public boolean isSingletonCurrentlyInCreation(String beanName) { return this.singletonsCurrentlyInCreation.containsKey(beanName); } protected void beforeSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.containsKey(beanName) && this.singletonsCurrentlyInCreation.put(beanName, Boolean.TRUE) != null) { throw new BeanCurrentlyInCreationException(beanName); } } protected void afterSingletonCreation(String beanName) { if (!this.inCreationCheckExclusions.containsKey(beanName) && !this.singletonsCurrentlyInCreation.remove(beanName)) { throw new IllegalStateException("Singleton '" + beanName + "' isn't currently in creation"); } } public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) { Assert.notNull(beanName, "'beanName' must not be null"); synchronized (this.singletonObjects) { Object singletonObject = this.singletonObjects.get(beanName); if (singletonObject == null) { ... beforeSingletonCreation(beanName); ... if (recordSuppressedExceptions) { this.suppressedExceptions = new LinkedHashSet<Exception>(); } try { ... } catch (BeanCreationException ex) { ... } finally { ... afterSingletonCreation(beanName); } addSingleton(beanName, singletonObject); } ... } }AbstractAutowireCapableBeanFactory类代码
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) { ... boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { ... addSingletonFactory(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException { return getEarlyBeanReference(beanName, mbd, bean); } }); } ... if (earlySingletonExposure) { Object earlySingletonReference = getSingleton(beanName, false);//会调用上面的ObjectFactory.getObject()方法 ... } ... return exposedObject; }4.6、加载bean定义,这个过程比较复杂,限于篇幅放到专门的文章分析。大致流程是:定位bean配置文件(ResourceLoader)-》解析Bean定义文件(BeanDefinitionDocumentReader)-》把bean定义解析成一个个的BeanDefinition对象,并且注册到容器中
5、给上一步创建的Bean工厂做一些准备工作,比如给Bean工厂注册类加载器PropertyEditor处理器,注册loadTimeWeaver、systemProperties、systemEnvironment等特殊bean
5.1、设置类加载器,如果没有设置,默认类加载器优先取当前线程上下文类加载器,如果未取到取ClassUtils类的类加载器,如果没取到取系统类加载器
public static ClassLoader getDefaultClassLoader() { ClassLoader cl = null; try { cl = Thread.currentThread().getContextClassLoader(); } catch (Throwable ex) { // Cannot access thread context ClassLoader - falling back... } if (cl == null) { // No thread context class loader -> use class loader of this class. cl = ClassUtils.class.getClassLoader(); if (cl == null) { // getClassLoader() returning null indicates the bootstrap ClassLoader try { cl = ClassLoader.getSystemClassLoader(); } catch (Throwable ex) { // Cannot access system ClassLoader - oh well, maybe the caller can live with null... } } } return cl; }5.2、设置EL表达式处理器StandardBeanExpressionResolver
5.3、增加默认的PropertyEditor注册器ResourceEditorRegistrar
在bean定义xml中,只能用字符串来表示value,PropertyEditor就是把这些字符串转换成相应的java类型值,Spring框架会根据bean属性的类型来决定采用哪个具体的PropertyEditor,比如布尔类型就用BooleanEditor,Class类型就使用ClassEditor,框架定义了一些默认的PropertyEditor,代码在PropertyEditorRegistrySupport类中。
private void createDefaultEditors() { this.defaultEditors = new HashMap<Class<?>, PropertyEditor>(64); ... this.defaultEditors.put(Charset.class, new CharsetEditor()); this.defaultEditors.put(Class.class, new ClassEditor()); ... // Only register config value editors if explicitly requested. if (this.configValueEditorsActive) { StringArrayPropertyEditor sae = new StringArrayPropertyEditor(); this.defaultEditors.put(String[].class, sae); this.defaultEditors.put(short[].class, sae); this.defaultEditors.put(int[].class, sae); this.defaultEditors.put(long[].class, sae); } }此外在框架中对PropertyEditor还做了一次内置的扩展,比如URLEditor、FileEditor,功能是通过ResourceLoader加载value中的路径对应的File或URL设置到对应的属性上,其中通过PropertyResolver接口来处理路径中出现的占位符,这次扩展工作就是由此处添加的ResourceEditorRegistrar来完成。另外可以在bean定义文件中扩展应用层定义的PropertyEditor,通过CustomEditorConfigurer来完成,它是一个BeanFactoryPostProcessor,比如下面的代码例子就是自定义了一个日期类型的转换器并且注册到容器中。
public class DateEditor extends PropertyEditorSupport { private DateFormat dateFormat; public void setDateFormat(String dateFormat) { this.dateFormat = new SimpleDateFormat(dateFormat); } @Override public void setAsText(String text) throws IllegalArgumentException { try { Object value = dateFormat.parse(text); setValue(value); } catch (ParseException e) { e.printStackTrace(); } } @Override public String getAsText() { if (getValue() instanceof Date) { Date d = (Date) getValue(); return dateFormat.format(d); } return super.getAsText(); } } public class DateBean { private Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public static void main(String[] args) { BeanFactory context = new ClassPathXmlApplicationContext( "spring/beans/propertyeditor/propertyeditor.xml"); DateBean dateBean = (DateBean) context.getBean("dateBean"); System.out.println(dateBean.getDate()); Calendar cal = Calendar.getInstance(); dateBean.setDate(cal.getTime()); System.out.println(dateBean.getDate()); } } <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date" value-ref="dateEditor"></entry> </map> </property> </bean> <bean id="dateEditor" class="spring.beans.propertyeditor.DateEditor"> <property name="dateFormat" value="yyyy-MM-dd HH:mm:ss" /> </bean> <bean id="dateBean" class="spring.beans.propertyeditor.DateBean"> <property name="date" value="2014-06-01 09:21:20" /> </bean>5.4、注册Aware接口处理器ApplicationContextAwareProcessor,这是一个BeanPostProcessor,它的职责是在bean创建完成之后触发该bean实现的所有Aware接口,比如ApplicationContextAware接口的setApplicationContext方法,EnvironmentAware接口的setEnvironment,xxxAware接口可以让应用代码持有容器中关键对象(比如ApplicationContext、Environment等)的引用,核心代码在ApplicationContextAwareProcessor的invokeAwareInterfaces方法:
private void invokeAwareInterfaces(Object bean) { if (bean instanceof Aware) { if (bean instanceof EnvironmentAware) { ((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment()); } if (bean instanceof EmbeddedValueResolverAware) { ((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver( new EmbeddedValueResolver(this.applicationContext.getBeanFactory())); } if (bean instanceof ResourceLoaderAware) { ((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext); } if (bean instanceof ApplicationEventPublisherAware) { ((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext); } if (bean instanceof MessageSourceAware) { ((MessageSourceAware) bean).setMessageSource(this.applicationContext); } if (bean instanceof ApplicationContextAware) { ((ApplicationContextAware) bean).setApplicationContext(this.applicationContext); } } }5.5、注册几个自动装配相关的类和实例
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); beanFactory.registerResolvableDependency(ResourceLoader.class, this); beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); beanFactory.registerResolvableDependency(ApplicationContext.class, this);
这样的话容器就把bean工厂和ApplicationContext跟上面几个类型绑定了,在应用代码就可以通过类型自动装配把工厂实例和ApplicationContext实例设置到自定义bean的属性中。像下面的例子,beanFactory、resourceLoader、appContext、appEventPublisher这几个属性都会被自动设置,虽然没有在显示的在bean定义xml中注入它们。
public class AutowireByTypeBean { private Bean1 bean1; private BeanFactory beanFactory; private ResourceLoader resourceLoader; private ApplicationEventPublisher appEventPublisher; private ApplicationContext appContext; public BeanFactory getBeanFactory() { return beanFactory; } public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } public ResourceLoader getResourceLoader() { return resourceLoader; } public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } public ApplicationEventPublisher getAppEventPublisher() { return appEventPublisher; } public void setAppEventPublisher(ApplicationEventPublisher appEventPublisher) { this.appEventPublisher = appEventPublisher; } public ApplicationContext getAppContext() { return appContext; } public void setAppContext(ApplicationContext appContext) { this.appContext = appContext; } public Bean1 getBean1() { return bean1; } public void setBean1(Bean1 bean1) { this.bean1 = bean1; } } <bean id="autowireBean" class="spring.beans.autowire.AutowireByTypeBean" autowire="byType"></bean> <bean id="bean1111" class="spring.beans.autowire.Bean1"> <property name="id" value="1"></property> </bean>
5.6、处理LTW(LoadTimeWeaver) aware接口,增加一个bean后处理器LoadTimeWeaverAwareProcessor,让所有实现了LoadTimeWeaverAware接口的bean都可以持有LTW实例,代码在prepareBeanFactory方法
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); // Set a temporary ClassLoader for type matching. beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); }
AOP切面织入有三种方式:编译期织入、类加载期织入和运行期织入。编译期织入是指在Java编译期,采用特殊的编译器,将切面织入到Java类中;而类加载期织入则指通过特殊的类加载器(ClassFileTransformer),在类字节码加载到JVM时,织入切面;运行期织入则是采用CGLib工具或JDK动态代理进行切面的织入,LTW是类加载期织入方式。下面是LTW的代码例子:
定义切面类,下面的切面是拦截方法调用并且在方法调用前后分别打印一行begin和end信息
@Aspect public class MethodAroundAspect { @Around("aroundMethod()") public Object around(ProceedingJoinPoint pjp) throws Throwable { System.out.println(pjp.getSignature().getName() + " begin..."); Object result = pjp.proceed(); System.out.println(pjp.getSignature().getName() + " end..."); return result; } @Pointcut("execution(public * spring.beans.ltw..*(..))") public void aroundMethod() { } }
在META-INF目录下添加aop.xml文件,注意文件夹和文件名必须是META-INF和aop.xml,添加如下配置,定义切面并且织入范围,下面的配置文件声明了切面织入到spring.beans.ltw包下的所有类
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd"> <aspectj> <weaver> <include within="spring.beans.ltw.*" /> </weaver> <aspects> <aspect name="spring.beans.ltw.MethodAroundAspect" /> </aspects> </aspectj>编织器注入到容器中,框架在解析context:load-time-weaver标签时,把该标签解析成id为loadTimeWeaver类型为DefaultContextLoadTimeWeaver的bean,这个bean就是LTW编织器,此外还会额外生成一个AspectJWeavingEnabler类型的bean注册到容器中,这个bean实现了BeanFactoryPostProcessor、BeanClassLoaderAware、LoadTimeWeaverAware接口,会被自动注入bean类加载器、LTW实例,为LTW注册字节码转换器,主逻辑在enableAspectJWeaving方法中。aspectj-weaving属性有三个枚举值:on、off、autodetect,分别是打开、关闭、自动检测,如果设置成autodetect,容器会检查应用是否定义了META-INF/aop.xml文件,主逻辑在LoadTimeWeaverBeanDefinitionParser的isAspectJWeavingEnabled方法。
<context:load-time-weaver aspectj-weaving="autodetect" /> <context:component-scan base-package="spring.beans.ltw"></context:component-scan> <bean id="ltwBean" class="spring.beans.ltw.LTWBean"></bean>
public static void enableAspectJWeaving(LoadTimeWeaver weaverToUse, ClassLoader beanClassLoader) { if (weaverToUse == null) { if (InstrumentationLoadTimeWeaver.isInstrumentationAvailable()) { weaverToUse = new InstrumentationLoadTimeWeaver(beanClassLoader); } else { throw new IllegalStateException("No LoadTimeWeaver available"); } } weaverToUse.addTransformer(new AspectJClassBypassingClassFileTransformer( new ClassPreProcessorAgentAdapter())); }
protected boolean isAspectJWeavingEnabled(String value, ParserContext parserContext) { if ("on".equals(value)) { return true; } else if ("off".equals(value)) { return false; } else { // Determine default... ClassLoader cl = parserContext.getReaderContext().getResourceLoader().getClassLoader(); return (cl.getResource(AspectJWeavingEnabler.ASPECTJ_AOP_XML_RESOURCE) != null); } }主要代码完成之后,写代码测试
BeanFactory context = new ClassPathXmlApplicationContext( "spring/beans/ltw/ltw.xml"); LTWBean ltwBean = (LTWBean) context.getBean("ltwBean"); ltwBean.run();控制台会打印出下面的内容,说明切面编织成功
run begin... LTWBean run... run end...
5.7、注册坏境bean
- 检查当前Context是否定义了id为environment的bean,如果没有定义,把StandardEnvironment注册到容器中,id为environment,这个bean包含了所有系统变量和环境变量
- 检查当前Context是否定义了id为systemProperties,如果没有定义,把系统变量Map注册到容器中,id为systemProperties
- 检查当前Context是否定义了id为systemEnvironment,如果没有定义,把环境变量Map注册到容器中,id为systemEnvironment
6、激活所有BeanFactoryPostProcessor接口,包括容器内置的和应用自定义的,所有的BFPP实现了PriorityOrdered接口归类并排序,实现了Ordered接口的归类并排序,未实现排序接口的归类,先按顺序执行实现了PriorityOrdered接口的BFPP,然后按顺序执行实现了Ordered接口的BFPP,最后执行未实现排序接口的BFPP。其中还有个特殊的BFPPBeanDefinitionRegistryPostProcessor接口,它是用来扩展一些特殊的Bean定义,比如有个实现ConfigurationClassPostProcessor,它是用来处理@Configuration注解描述的bean定义,在bean定义文件中定义了<context:annotation-config
/>标签之后,容器会自动注册一个ConfigurationClassPostProcessor来对指定包中包含@Configuration注解的类进行解析。
7、把所有实现BeanPostProcessor接口的bean注册到工厂中,为后面激活这些BPP做准备,所有实现了PriorityOrdered接口的归类并排序,实现了Ordered接口的归类并排序,未实现排序接口的归类,还有一个BPP扩展MergedBeanDefinitionPostProcessor接口,实现了这个接口的bean也单独归类,这个接口在容器中有一些实现:AutowiredAnnotationBeanPostProcessor、InitDestroyAnnotationBeanPostProcessor、RequiredAnnotationBeanPostProcessor、ApplicationListenerDetector,它们分别处理@Autowired、@PostConstructed和@PreDestroy注解、@Required注解、检测ApplicationListener接口。容器会额外注册一个ApplicationListenerDetector
BPP用来检测所有实现了ApplicationListener接口的bean并把它们注册到Application时间广播器中,当容器事件被激活时事件会传递到这些实现了ApplicationListener接口的bean
8、处理国际化资源bean,检查是否定义了名为messageSource的bean,如果已经注册,用这个bean来处理国际化资源,这个bean必须是实现了MessageSource接口的bean,Spring中有个默认的国际化资源实现ResourceBundleMessageSource,它是基于JDK中的ResourceBundle实现的,用法如下:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource"> <property name="basenames"> <list> <value>spring.beans.messagesource.message</value> </list> </property> </bean> ApplicationContext context = new ClassPathXmlApplicationContext( "spring/beans/messagesource/messagesource.xml"); String name = context.getMessage("cyy.name", null, Locale.ENGLISH);在spring/beans/messagesource目录下需要增加message_zh.properties、message_en.properties等资源文件
9、初始化容器事件广播器
检查是否定义了applicationEventMulticaster名称的bean,如果没有创建SimpleApplicationEventMulticaster实例记录到容器,用来广播容器事件到各个队容器事件感兴趣的监听者
protected void initApplicationEventMulticaster() { ConfigurableListableBeanFactory beanFactory = getBeanFactory(); if (beanFactory.containsLocalBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME)) { this.applicationEventMulticaster = beanFactory.getBean(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, ApplicationEventMulticaster.class); } else { this.applicationEventMulticaster = new SimpleApplicationEventMulticaster(beanFactory); beanFactory.registerSingleton(APPLICATION_EVENT_MULTICASTER_BEAN_NAME, this.applicationEventMulticaster); } }
10、把应用层注册的容器事件监听器添加到容器中
和ApplicationListenerDetector作用重复,但是ApplicationListenerDetector能够检查到实现了ApplicationListener接口的内嵌Bean,而这一步只能检查到实现了ApplicationListener接口的顶层bean
protected void registerListeners() { // Register statically specified listeners first. for (ApplicationListener<?> listener : getApplicationListeners()) { getApplicationEventMulticaster().addApplicationListener(listener); } // Do not initialize FactoryBeans here: We need to leave all regular beans // uninitialized to let post-processors apply to them! String[] listenerBeanNames = getBeanNamesForType(ApplicationListener.class, true, false); for (String lisName : listenerBeanNames) { getApplicationEventMulticaster().addApplicationListenerBean(lisName); } }
11、结束Bean工厂的初始化,清理一些变量并且预加载创建单例Bean
- 检查是否定义了conversionService名称的bean,如果是把这个bean当做容器的类型转换器
- 提前初始化LTW bean,把类转换器(ClassFileTransformer)提前注册到类加载器中,为切面编织做准备
- 清空临时类加载器
- 冻结所有bean定义,让它们不能再被修改
- 提前初始化单例bean,检查所有bean,如果bean有父bean,把父bean和子bean的属性信息合并,检查bean是否是非抽象、单例、没有设置lazy-init,如果是初始化bean。这个步骤比较复杂,需要一篇专门的文章分析
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) { // Initialize conversion service for this context. if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) && beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) { beanFactory.setConversionService( beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)); } // Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early. String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false); for (String weaverAwareName : weaverAwareNames) { getBean(weaverAwareName); } // Stop using the temporary ClassLoader for type matching. beanFactory.setTempClassLoader(null); // Allow for caching all bean definition metadata, not expecting further changes. beanFactory.freezeConfiguration(); // Instantiate all remaining (non-lazy-init) singletons. beanFactory.preInstantiateSingletons(); }
12、结束容器刷新
- 注册lifecycle处理器lifecycleProcessor到容器,检查是否定义了lifecycleProcessor名称的bean,如果没有创建一个DefaultLifecycleProcessor实例,并且注册到容器中,用它来处理容器的lifecycle
- 传播容器的refresh事件到lifecycleProcessor
- 广播容器刷新事件,所有实现了ApplicationListener事件的bean都可以监听到该事件
protected void finishRefresh() { // Initialize lifecycle processor for this context. initLifecycleProcessor(); // Propagate refresh to lifecycle processor first. getLifecycleProcessor().onRefresh(); // Publish the final event. publishEvent(new ContextRefreshedEvent(this)); // Participate in LiveBeansView MBean, if active. LiveBeansView.registerApplicationContext(this); }
Assert.notNull(autowireCandidateResolver, "AutowireCandidateResolver must not be null");
if ( autowireCandidateResolver instanceof BeanFactoryAware) {
if (System.getSecurityManager() != null) {
final BeanFactory target = this;
AccessController.doPrivileged(new PrivilegedAction<Object>() {
@Override
public Object run() {
((BeanFactoryAware) autowireCandidateResolver). setBeanFactory(target);
return null;
}
}, getAccessControlContext());
}
else {
((BeanFactoryAware) autowireCandidateResolver).setBeanFactory(this);
}
}
this.autowireCandidateResolver = autowireCandidateResolver;
}
/**
* Callback that supplies the owning factory to a bean instance.
* <p>Invoked after the population of normal bean properties
* but before an initialization callback such as
* {@link InitializingBean#afterPropertiesSet()} or a custom init-method.
* @param beanFactory owning BeanFactory (never {@code null}).
* The bean can immediately call methods on the factory.
* @throws BeansException in case of initialization errors
* @see BeanInitializationException
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;
}