SpringIOC
IOC的概念我不想赘述,参考《Spring揭秘》一书的具体讲解. 核心就是解耦.
- IoC容器的职责: 1. 对象的构造 2.对象间依赖管理
- 好处:解耦主体对象和其依赖的构造逻辑,直接调用依赖的服务即可.
- Spring中IOC容器包含: 1.BeanFactory 2. ApplicationContext
前者是父类,后者提供了更丰富的功能.
前者懒加载,后者相反. - ApplicationContext包含了一些非常有用的功能,比如和国际化相关的MessageSource,统一Resource的ResourceLoader和事件监听发布相关的ApplicationEventPublisher
- WebApplicationContext是ApplicationContext的子类,这主要涉及的就是SpringMVC的功能,这会新开一章
xml中的<bean>
如何成为spring容器中的对象
xml配置信息是硬盘上的文件,而被运行着的spring容器管理则是被加载到内存中了.
这其中比如涉及很多转化过程.我依照我的理解简单罗列一下:
-
容器首先要启动,这个启动阶段就有很多事情能做了
- XxxBeanDefinitionReader读取配置信息,转为BeanDefinition,注册到BeanDefinitionRegistry中
-
通过容器的getBean()获取实例化后的对象.实例化过程中就会使用BeanDefinition
- 我们可以在此阶段通过多种途径魔改BeanDefinition,实现接口,xml配置和注解配置皆可.(注意顺序).当然Spring本身也有用到此机制,比如:
PropertyPlaceholderConfigurer
,PropertyOverrideConfigurer
,CustomEditorConfigurer
- 我们可以在此阶段通过多种途径魔改BeanDefinition,实现接口,xml配置和注解配置皆可.(注意顺序).当然Spring本身也有用到此机制,比如:
-
1.容器启动阶段
PropertiesBeanDefinitionReader和XmlBeanDefinitionReader是BeanDefinitionReader的两个实现类
这些BeanDefinition会注册到BeanDefinitionRegistry中 -
2.Bean实例化阶段
当请求方显式或隐式地调用容器的getBean方法时,容器会检查是否已经初始化,没有的话且存在其对应的BeanDefinition实例时就实例化被请求对象,并为该对象进行依赖注入(DI,这恰恰时IOC容器要做的事情). -
BeanFactoryPostProcessor允许我们在Bean实例化之前
对BeanDefinition进行一些魔改
.
Ordered可以让我们指定顺序.
BeanFactoryPostProcessor实现类包括PropertyPlaceholderConfigurer , PropertyOverrideConfigurer -
BeanFactoryPostProcessor实现类之PropertyPlaceholderConfigurer, 对BeanDefinition进行了修改
PropertyPlaceholderConfigurer 允许我们在XML中使用占位符来引用上面的文件.
- BeanFactoryPostProcessor实现类之
PropertyOverrideConfigurer
可以允许在properties中覆盖某个属性的值. - BeanFactoryPostProcessor实现类之
CustomEditorConfigurer
,辅助性的将后期可能用到的信息注册到容器中,没有更改BeanDifinition.
XML或其他类型的配置文件都是字符串,怎么把这些String转变为各种类型?那必然需要转换器,而转换器又首先依赖转换规则,这个类就是来传达这个转换信息的.
Spring为String到每种对象类型的转换提供一个PropertyEditor,这些PropertyEditors后续会被BeanWrapper使用.
StringArrayPropertyEditor
ClassEditor: Class.forName(String)
FileEditor
LocaleEditor
Bean实例化的生命周期
- Bean的实例化与BeanWrapper
Bean的实例化有不同的方式:反射
,cglib动态字节码生成
,其他
返回的实例实际是BeanWrapper,如何证明?
BeanWrapper是一个PropertyAccessor, 以统一的方式对属性进行进行访问.
还是一个PropertyEditorRegistry,参见BeanFactoryPostProcessor实现类之CustomEditorConfigurer
BeanWrapper的一个优点是方便设置属性(相对反射API而言) - 各种Aware接口,暂且略去
- BeanProcessor不是BeanFactoryProcessor,在此阶段可以替换实例,AOP就常常这么干。
他是spring的一个扩展点
上面Aware接口实际就是通过它来处理的。
当ApplicationContext中每个对象的实例化过程走到BeanPostProcessor前置处理这一步时,ApplicationContext容器会检测到之前注册到容器的ApplicationContextAwareProcessor这个BeanPostProcessor的实现类,然后就会调用其postProcessBeforeInitialization()方法,检查并设置Aware相关依赖。
AOP实现可以参考AbstractAutoProxyCreator的该实现方法,用来生成一个代理的对象。
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
- 如果实现了InitializaingBean那就调用afterPropertiesSet方法。不过通常不要用,因为要用就得implements 这个接口,显得侵入性比较强。一种更好的方式是XML配置中bean有个属性是init-method,这个例子可以看书上
public interface InitializingBean {
/**
名字起得挺好,当实例化过程中完成所有属性的设置后才会调用
*/
void afterPropertiesSet() throws Exception;
}
- 如果实现了DisposableBean 那就调给这个bean注册一个销毁时调用的回调方法。用法同上。
主要应用场景是数据库连接池的销毁。
不过这里有个坑,可能不会自动调用,这些细节暂且搁置。
public interface DisposableBean {
/**
* bean销毁的时候会调用,通常就是干一些释放资源的事情
*/
void destroy() throws Exception;
}
spring的统一资源加载策略
11