ApplicationContext包含BeanFactory的所有功能,并且可以对BeanFactory现有的功能进行扩展。绝大多数典型的企业应用和系统,使用的都是ApplicationContext而不是直接使用BeanFactory。下面看一下ApplicationContext相对于BeanFactory扩展了哪些功能。
//BeanFactory的加载配置文件的方式:
BeanFactory bf = new XmlBeanFactory(new ClassPathResource("beanFactoryTest.xml"));
//ApplicationContext加载配置文件的方式:
ApplicationContext bf = new ClassPathXmlApplicationContext("");
继续根据ClassPathXmlApplicationContext进行跟踪:
public ClassPathXmlApplicationContext(String configLocation) throws BeansException {
this(new String[]{configLocation}, true, (ApplicationContext)null);
}
//根据this继续走:
public ClassPathXmlApplicationContext(String[] configLocations, boolean refresh, ApplicationContext parent) throws BeansException {
super(parent);
//将配置文件的路径以数组的方式传入。
this.setConfigLocations(configLocations);
if(refresh) {
//解析和功能实现。
this.refresh();
}
}
继续跟踪setConfigLocations:
public void setConfigLocations(String... locations) {
if(locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for(int i = 0; i < locations.length; ++i) {
//解析给定路径,如果数组总包含特殊符号,如${var},那么resolvePath中会搜寻系统的变量被替换。
this.configLocations[i] = this.resolvePath(locations[i]).trim();
}
} else {
this.configLocations = null;
}
}
继续跟踪refresh函数:
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
//准备刷新上下文环境,例如对系统属性或者环境变量进行准备及验证。
this.prepareRefresh();
//初始化BeanFactory,并进行XML文件的读取,这一步骤要服用BeanFactory的配置文件读取的以及其他功能。
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
//对BeanFactory进行各种功能填充。@Qualifier和@Autowired是在此步骤增加的支持。
this.prepareBeanFactory(beanFactory);
try {
//子类覆盖方法做额外的处理。
this.postProcessBeanFactory(beanFactory);
//激活各种BeanFactory处理器
this.invokeBeanFactoryPostProcessors(beanFactory);
//注册拦截Bean创建的Bean处理器,这里只是注册,真正的调用是在getBean的时候
this.registerBeanPostProcessors(beanFactory);
//为上下文初始化Mesagge源,即不同语言的消息体,国际化处理。
this.initMessageSource();
//初始化应用消息广播器,并放入applicationEventMulticaster中
this.initApplicationEventMulticaster();
//留给子类来初始化其他的bean
this.onRefresh();
//在所有注册的bean中查找Listener bean,注册到消息广播器中。
this.registerListeners();
//初始化剩下的单例。
this.finishBeanFactoryInitialization(beanFactory);
//完成刷新过程。
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
this.destroyBeans();
this.cancelRefresh(var9);
throw var9;
} finally {
this.resetCommonCaches();
}
}
}
继续跟踪refresh方法中的this.prepareRefresh()方法:
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if(this.logger.isInfoEnabled()) {
this.logger.info("Refreshing " + this);
}
//留给子类覆盖。
this.initPropertySources();
//验证需要的属性文件是否都已经放入环境中。
this.getEnvironment().validateRequiredProperties();
this.earlyApplicationEvents = new LinkedHashSet();
}
上述留给子类覆盖的方法initPropertySources使用举例:
class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{
public MyClassPathXmlApplicationContext(String ... configLocations) {
super(configLocations);
}
@Override
protected void initPropertySources() {
getEnvironment().setRequiredProperties("VAR");
}
}
//读取配置文件时这样调用:
ApplicationContext bf2 = new MyClassPathXmlApplicationContext("");
继续跟踪refresh方法中的this.obtainFreshBeanFactory()方法:
//通过了这个函数以后,ApplicationContext就已经拥有了BeanFactory的全部功能。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
//初始化BeanFactory,并进行XML文件读取,并将得到的BeanFactory记录在当前实体的属性中,
this.refreshBeanFactory();
//返回当前实体的beanFactory
ConfigurableListableBeanFactory beanFactory = this.getBeanFactory();
if(this.logger.isDebugEnabled()) {
this.logger.debug("Bean factory for " + this.getDisplayName() + ": " + beanFactory);
}
return beanFactory;
}
//上面的this.refreshBeanFactory()方法源码:
protected final void refreshBeanFactory() throws BeansException {
if(this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
//创建DefaultListableBeanFactory
DefaultListableBeanFactory ex = this.createBeanFactory();
//为了反序列化指定id,如果需要,让这个BeanFactory从id反序列化到BeanFactory对象。
ex.setSerializationId(this.getId());
//定制beanFactory,设置相关属性,包括是否允许覆盖同名称的不同定义的对象以及循环依赖
//设置@Autowired和@Qualitier注册解析器QualifierAnnotationAutowireCandidateResolver
this.customizeBeanFactory(ex);
//初始化DocumentReader,并进行XML文件读取及解析。
this.loadBeanDefinitions(ex);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = ex;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
//跟踪上面的this.customizeBeanFactory(ex)方法:
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
//是否允许覆盖同名称的不同定义的对象。
if(this.allowBeanDefinitionOverriding != null) {
beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding.booleanValue());
}
//是否允许bean之间存在循环依赖。
if(this.allowCircularReferences != null) {
beanFactory.setAllowCircularReferences(this.allowCircularReferences.booleanValue());
}
}
//关于上面方法中allowBeanDefinitionOverriding和allowCircularReferences的变量设置举例:
class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{
@Override
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
super.setAllowBeanDefinitionOverriding(false);
super.setAllowCircularReferences(false);
super.customizeBeanFactory(beanFactory);
}
}
//继续走this.loadBeanDefinitions(ex),此方法是用来加载BeanDefinition
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//对上一步创建的beanDefinitionReader进行环境变量的设置。
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
//对beanDefinitionReader进行设置,可以覆盖。
this.initBeanDefinitionReader(beanDefinitionReader);
this.loadBeanDefinitions(beanDefinitionReader);
}
//继续查看this.loadBeanDefinitions(beanDefinitionReader)
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
Resource[] configResources = this.getConfigResources();
if(configResources != null) {
reader.loadBeanDefinitions(configResources);
}
String[] configLocations = this.getConfigLocations();
if(configLocations != null) {
reader.loadBeanDefinitions(configLocations);
}
}
继续跟踪refresh方法中的this.prepareBeanFactory(beanFactory)
//源码如下:
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
//设置beanFactory的classLoader为当前的classLoader。
beanFactory.setBeanClassLoader(this.getClassLoader());
//默认可以使用EL表达式
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
//为beanFactory增加了一个默认propertyEditor,主要是对bean的属性等设置管理的一个工具。
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, this.getEnvironment()));
//添加PostProcessor
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
//设置几个自动装配的特殊规则
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
//增加对ApectJ的支持
if(beanFactory.containsBean("loadTimeWeaver")) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}
if(!beanFactory.containsLocalBean("environment")) {
beanFactory.registerSingleton("environment", this.getEnvironment());
}
if(!beanFactory.containsLocalBean("systemProperties")) {
beanFactory.registerSingleton("systemProperties", this.getEnvironment().getSystemProperties());
}
//增加默认环境bean.
if(!beanFactory.containsLocalBean("systemEnvironment")) {
beanFactory.registerSingleton("systemEnvironment", this.getEnvironment().getSystemEnvironment());
}
}
/**
setBeanExpressionResolver注册语言解析器,就可以对SPEL进行解析了,
真正调用这个解析器是在Spring对bean进行初始化时的属性填充这步,
在这一步中Spring会调用AbstractAutowireCapableBeanFactory类中的applyPropertyValues函数来完成。
**/
上述方法中对bean的属性等设置管理说明:在SpringDI注入的时候可以把普通属性注入进来,但是像Date这种类型就无法被识别。例如:
class UserManager{
private Date dataValue;
public Date getDataValue() {
return dataValue;
}
public void setDataValue(Date dataValue) {
this.dataValue = dataValue;
}
}
//上述代码中需要对日期类型的属性进行注入:
<bean id="userManager" class com.test.UserManager>
<property name="dataValue">
<value>2013-03-15</value>
</property>
</bean>
//测试
ApplicationContext bf = new ClassPathXmlApplicationContext("");
UserManager userManager = (UserManager)bf.getBean("userManager");
System.out.println(userManager);
如果直接这样使用,程序会报错,类型转换不成功。String无法转换成Date类型。spring针对这类问题提供了两种解决办法:
1.自定义属性编辑器,通过继承PropertyEditorSupport.
//编写自定义的属性编辑器
class DatePropertyEditor extends PropertyEditorSupport{
private String format = "yyyy-MM-dd";
public void setFormat(String format) {
this.format = format;
}
public void setAsText(String arg0) throws IllegalArgumentException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
try {
Date d = sdf.parse(arg0);
} catch (ParseException e) {
e.printStackTrace();
}
}
}
//将自定义属性编辑器注册到Spring中。
<bean class="org.Springframework.beans.factory.config.CustomEditorConfigurer">
<property name="customEditors">
<map>
<entry key="java.util.Date">
<bean class="com.test.DatePropertyEditor">
<property name="format" value="yyyy-MM-dd"/>
</bean>
</map>
</property>
</bean>
2.注册Spring自带的属性编辑器CustomDateEditor
//定义属性编辑器
class DatePropertyEditorRegostrar implements PropertyEditorRegistrar{
@Override
public void registerCustomEditors(PropertyEditorRegistry propertyEditorRegistry) {
propertyEditorRegistry.registerCustomEditor(Date.class,new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"),true));
}
}
//注册到spring
<bean class="org.Springframework.beans.factory.config.CustomEditorConfigurer">
<property name="propertyEditorRegistrars">
<list>
<bean class="com.test.DatePropertyEditorRegistrar"></bean>
</list>
</property>
</bean>
ResourceEditorRegistrar中也实现了registerCustomEditors方法:
//源码如下:
public void registerCustomEditors(PropertyEditorRegistry registry) {
ResourceEditor baseEditor = new ResourceEditor(this.resourceLoader, this.propertyResolver);
this.doRegisterEditor(registry, Resource.class, baseEditor);
this.doRegisterEditor(registry, ContextResource.class, baseEditor);
this.doRegisterEditor(registry, InputStream.class, new InputStreamEditor(baseEditor));
this.doRegisterEditor(registry, InputSource.class, new InputSourceEditor(baseEditor));
this.doRegisterEditor(registry, File.class, new FileEditor(baseEditor));
if(pathClass != null) {
this.doRegisterEditor(registry, pathClass, new PathEditor(baseEditor));
}
this.doRegisterEditor(registry, Reader.class, new ReaderEditor(baseEditor));
this.doRegisterEditor(registry, URL.class, new URLEditor(baseEditor));
ClassLoader classLoader = this.resourceLoader.getClassLoader();
this.doRegisterEditor(registry, URI.class, new URIEditor(classLoader));
this.doRegisterEditor(registry, Class.class, new ClassEditor(classLoader));
this.doRegisterEditor(registry, Class[].class, new ClassArrayEditor(classLoader));
if(this.resourceLoader instanceof ResourcePatternResolver) {
this.doRegisterEditor(registry, Resource[].class, new ResourceArrayPropertyEditor((ResourcePatternResolver)this.resourceLoader, this.propertyResolver));
}
}
//继续追踪doRegisterEditor:
private void doRegisterEditor(PropertyEditorRegistry registry, Class<?> requiredType, PropertyEditor editor) {
if(registry instanceof PropertyEditorRegistrySupport) {
((PropertyEditorRegistrySupport)registry).overrideDefaultEditor(requiredType, editor);
} else {
//前面提到的自定义属性的关键代码在此被调用
registry.registerCustomEditor(requiredType, editor);
}
}
查找了registerCustomEditors方法被调用的位置,发现AbstractBeanFactory类中的initBeanWrapper方法调用了此方法,这个方法是在bean初始化时使用的一个方法,主要作用就是将BeanDefinition转换为BeanWrapper后用于属性的填充。在bean初始化以后会调用ResourceEditorRegistrar的registerCustomEditors方法进行批量的通用属性编辑器注册。注册后,在属性填充的环节便可以直接让Spring使用这些编辑器进行属性的解析了。
BeanWrapper除了实现了BeanWrapperImpl还继承了PropertyEditorRegistrySupport,在该类中有这样一个方法:
/**
通过这个方法可以知道在spring中定义了上面一系列常用的属性编辑器,
如果我们定义的bean中的某个属性的类型不在上面的常用配置中,才需要我们进行个性化属性编辑器的注册。
**/
private void createDefaultEditors() {
this.defaultEditors = new HashMap(64);
this.defaultEditors.put(Charset.class, new CharsetEditor());
this.defaultEditors.put(Class.class, new ClassEditor());
this.defaultEditors.put(Class[].class, new ClassArrayEditor());
this.defaultEditors.put(Currency.class, new CurrencyEditor());
this.defaultEditors.put(File.class, new FileEditor());
this.defaultEditors.put(InputStream.class, new InputStreamEditor());
this.defaultEditors.put(InputSource.class, new InputSourceEditor());
this.defaultEditors.put(Locale.class, new LocaleEditor());
if(pathClass != null) {
this.defaultEditors.put(pathClass, new PathEditor());
}
this.defaultEditors.put(Pattern.class, new PatternEditor());
this.defaultEditors.put(Properties.class, new PropertiesEditor());
this.defaultEditors.put(Reader.class, new ReaderEditor());
this.defaultEditors.put(Resource[].class, new ResourceArrayPropertyEditor());
this.defaultEditors.put(TimeZone.class, new TimeZoneEditor());
this.defaultEditors.put(URI.class, new URIEditor());
this.defaultEditors.put(URL.class, new URLEditor());
this.defaultEditors.put(UUID.class, new UUIDEditor());
if(zoneIdClass != null) {
this.defaultEditors.put(zoneIdClass, new ZoneIdEditor());
}
this.defaultEditors.put(Collection.class, new CustomCollectionEditor(Collection.class));
this.defaultEditors.put(Set.class, new CustomCollectionEditor(Set.class));
this.defaultEditors.put(SortedSet.class, new CustomCollectionEditor(SortedSet.class));
this.defaultEditors.put(List.class, new CustomCollectionEditor(List.class));
this.defaultEditors.put(SortedMap.class, new CustomMapEditor(SortedMap.class));
this.defaultEditors.put(byte[].class, new ByteArrayPropertyEditor());
this.defaultEditors.put(char[].class, new CharArrayPropertyEditor());
this.defaultEditors.put(Character.TYPE, new CharacterEditor(false));
this.defaultEditors.put(Character.class, new CharacterEditor(true));
this.defaultEditors.put(Boolean.TYPE, new CustomBooleanEditor(false));
this.defaultEditors.put(Boolean.class, new CustomBooleanEditor(true));
this.defaultEditors.put(Byte.TYPE, new CustomNumberEditor(Byte.class, false));
this.defaultEditors.put(Byte.class, new CustomNumberEditor(Byte.class, true));
this.defaultEditors.put(Short.TYPE, new CustomNumberEditor(Short.class, false));
this.defaultEditors.put(Short.class, new CustomNumberEditor(Short.class, true));
this.defaultEditors.put(Integer.TYPE, new CustomNumberEditor(Integer.class, false));
this.defaultEditors.put(Integer.class, new CustomNumberEditor(Integer.class, true));
this.defaultEditors.put(Long.TYPE, new CustomNumberEditor(Long.class, false));
this.defaultEditors.put(Long.class, new CustomNumberEditor(Long.class, true));
this.defaultEditors.put(Float.TYPE, new CustomNumberEditor(Float.class, false));
this.defaultEditors.put(Float.class, new CustomNumberEditor(Float.class, true));
this.defaultEditors.put(Double.TYPE, new CustomNumberEditor(Double.class, false));
this.defaultEditors.put(Double.class, new CustomNumberEditor(Double.class, true));
this.defaultEditors.put(BigDecimal.class, new CustomNumberEditor(BigDecimal.class, true));
this.defaultEditors.put(BigInteger.class, new CustomNumberEditor(BigInteger.class, true));
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);
}
}
继续跟踪this.prepareBeanFactory(beanFactory)方法中的beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));,该方法主要还是用来注册BeanPostProcessor.
/**
该方法的重要逻辑都在ApplicationContextAwareProcessor中。
前面几章提到过Spring激活bean的init-method的前后,会调用BeanPostProcessor中的
postProcessBeforeInitialization和postProcessAfterInitialization方法。
ApplicationContextAwareProcessor类的源码实现:
**/
class ApplicationContextAwareProcessor implements BeanPostProcessor {
private final ConfigurableApplicationContext applicationContext;
private final StringValueResolver embeddedValueResolver;
public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
this.applicationContext = applicationContext;
this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
}
public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
AccessControlContext acc = null;
if(System.getSecurityManager() != null && (bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware || bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware || bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
acc = this.applicationContext.getBeanFactory().getAccessControlContext();
}
if(acc != null) {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
ApplicationContextAwareProcessor.this.invokeAwareInterfaces(bean);
return null;
}
}, acc);
} else {
this.invokeAwareInterfaces(bean);
}
return bean;
}
//通过此方法可以看出实现了Aware接口的bean在被初始化之后,可以获得一些对应的资源。之前设置的忽略自动装配的接口就是在此处生效的。
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(this.embeddedValueResolver);
}
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);
}
}
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}