延迟加载
Lazy-init 延迟加载,Bean 的延迟加载。 ApplicationContext 容器的默认行为是在启动服务器时所有 Singleton Bean 提前进行实例化。
配置方式
<!-- bean 的默认配置 -->
<bean id="wzkTestBean" class="wzk.WzkTestBean" lazy-init="false" />
false表示立即加载,在 Spring 启动时立刻进行实例初始化true表示延迟加载,第一次调用时才初始化
如果设置了一个立即加载的 bean1,引用了一个延迟加载的 bean2,那么 bean1 在容器启动时会初始化,此时 bean2 也会被实例化出来。
也可以使用 default-lazy-init 属性控制全局延时初始化:
<beans default-lazy-init="true">
<!-- no beans will be eagerly pre-instantiated... -->
</beans>
当 bean 的 scope 为 prototype 时,即使设置 lazy-init=false,容器启动时也不会立刻初始化,而是调用 getBean 方法时才实例化。
应用场景
- 开启延迟加载可以提高容器启动时的性能和运转性能
- 对于不经常使用的 Bean,偶尔加载时再实例化,节约资源
FactoryBean 和 BeanFactory
基础介绍
BeanFactory 接口是容器的顶级接口,定义了容器的基础行为,负责生产和管理 Bean 的工厂。具体使用它的子接口类型,如 ApplicationContext。
FactoryBean 是 Spring 中一种特殊的 Bean,可以生成某一个类型的对象实例,借助它可以自定义 Bean 的创建过程。Spring 中有两种 Bean:
- 普通 Bean
- 工厂 Bean(FactoryBean)
FactoryBean 与静态工厂方法和实例化工厂方法的作用类似,但在 Spring 框架和一些第三方框架整合时使用较多。
FactoryBean 接口方法
public interface FactoryBean<T> {
T getObject() throws Exception; // 获取实例化对象
Class<?> getObjectType(); // 返回对象类型
boolean isSingleton(); // 是否单例
}
代码示例
WzkCompany 实体类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class WzkCompany {
private String name;
private String address;
private String money;
}
WzkCompanyFactoryBean 实现类
public class WzkCompanyFactoryBean implements FactoryBean<WzkCompany> {
private String wzkCompanyInfo;
public void setWzkCompanyInfo(String wzkCompanyInfo) {
this.wzkCompanyInfo = wzkCompanyInfo;
}
@Override
public WzkCompany getObject() throws Exception {
WzkCompany wzkCompany = new WzkCompany();
String[] strs = wzkCompanyInfo.split(",");
wzkCompany.setName(strs[0]);
wzkCompany.setAddress(strs[1]);
wzkCompany.setMoney(strs[2]);
return wzkCompany;
}
@Override
public Class<?> getObjectType() {
return WzkCompany.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
XML 配置
<bean id="wzkCompanyBean" class="wzk.factory.WzkCompanyFactoryBean">
<property name="companyInfo" value="公司名字,公司地址,1000"></property>
</bean>
测试运行
// 获取 FactoryBean 创建的对象
Object wzkCompany = applicationContext.getBean("wzkCompanyBean");
// 输出:WzkCompany(name=公司名字, address=公司地址, money=1000)
// 获取 FactoryBean 本身,需要加 & 前缀
Object factoryBean = applicationContext.getBean("&wzkCompanyBean");
// 输出:wzk.factory.WzkCompanyFactoryBean@xxxx
后置处理器
Spring 提供了两种后处理 Bean 的扩展接口:
- BeanPostProcessor
- BeanFactoryPostProcessor
执行顺序:工厂初始化 BeanFactory → Bean 对象 → 在 BeanFactory 初始化之后使用 BeanFactoryPostProcessor → 在 Bean 实例化后使用 BeanPostProcessor
注意:对象不一定是 SpringBean,而 SpringBean 一定是个对象。
BeanPostProcessor
BeanPostProcessor 是针对 Bean 级别的处理,可以针对具体的某个 Bean 进行处理。
public interface BeanPostProcessor {
// 初始化方法前执行
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
// 初始化方法后执行
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
说明:
- 初始化方法指的是
init-method所指定的方法 - 默认会对整个 Spring 容器中所有的 Bean 进行处理
- 可以通过参数
beanName判断具体要处理的 Bean - 处理发生在 Spring 容器的实例化和依赖注入之后
BeanFactoryPostProcessor
BeanFactoryPostProcessor 是 BeanFactory 级别的处理,针对整个 Bean 工厂进行处理。典型应用如 PropertyPlaceholderConfigurer。
public interface BeanFactoryPostProcessor {
Factory(ConfigurableListableBeanFactory bean void postProcessBeanFactory) throws BeansException;
}
可以通过 getBeanDefinition 方法获取 BeanDefinition 对象,修改 Bean 标签中定义的属性值。
注意: 调用 BeanFactoryPostProcessor 方法时,Bean 还没有被实例化,此时 Bean 刚被解析为 BeanDefinition 对象。
总结
| 概念 | 说明 |
|---|---|
| BeanFactory | IOC 容器顶级接口,负责生产和管理 Bean |
| FactoryBean | 特殊 Bean,用于自定义 Bean 创建过程 |
| BeanPostProcessor | Bean 级别后处理,在初始化前后执行 |
| BeanFactoryPostProcessor | 工厂级别后处理,在 Bean 实例化前执行 |