BeanFactory和ApplicationContext
两者关系
BeanFactory | ApplicationContext |
---|---|
早期接口,被称为Spring的Bean工厂 | 后期更高级接口,称之为Spring 容器 |
BeanFactory的API更偏向底层 | API大多数是对BeanFactory底层API的封装; 且有更多的拓展功能:监听功能、国际化功能等 |
封装了Bean创建的主要逻辑和功能 | 继承了BeanFactory的功能 |
Bean的初始化时机不同,原始BeanFactory是在首次调用getBean时才进行Bean的创建 | ApplicationContext则是配置文件加载,容器一创建就将Bean都实例化并初始化好。 |
在Spring基础环境下,常用的三个ApplicationContext作用
实现类 | 功能描述 |
---|---|
ClassPathXmlApplicationContext | 加载类路径下的xml配置的ApplicationContext |
FileSystemXmlApplicationContext | 加载磁盘路径下的xml配置的ApplicationContext |
AnnotationConfigApplicationContext | 加载注解配置类的ApplicationContext |
在Spring的web环境下,常用的两个ApplicationContext作用
导入依赖
1 | <dependency> |
实现类 | 功能描述 |
---|---|
XmlWebApplicationContext | web环境下,加载类路径下的xml配置的ApplicationContext |
AnnotationConfigWebApplicationContext | web环境下,加载磁盘路径下的xml配置的ApplicationContext |
InitializingBean 接口
完成一些Bean的初始化操作
实现InitializingBean接口与在配置文件中指定init-method有什么不同?
如果同时实现了InitializingBean接口和init-method,那么系统会先调用InitializingBean再调用init-method指定的初始化方法。
总结
1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点
。但是init-method方式消除了对spring的依赖
3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法
。
Spring主要的实例化方式
构造方式实例化:底层通过构造方法对Bean进行实例化
- 无参构造方法实例化
- 有参构造方法实例化
添加参数
工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化
- 静态工厂方法实例化Bean
- 直接配置工厂对象及其静态方法配置
1
2
3
4
5
6
7
8// 工厂类
public class UserDaoFactoryBean {
// 静态工厂方法
public static UserDaoImpl userDaoImpl(String name, int age){
// 可以在此编写一些其他逻辑代码
return new UserDaoImpl(name, age);
}
}1
2
3
4<bean id="userDaoImpl" class="com.it.factory.UserDaoFactoryBean" factory-method="userDaoImpl">
<constructor-arg name="name" value="小🐕"/>
<constructor-arg name="age" value="18"/>
</bean>- 实例工厂方法实例化Bean
- 先有工厂对象,再用工厂对象去调用非静态方法
1
2
3
4
5
6
7<!-- 配置实例工厂Bean -->
<bean id="userDaoFactoryBean2" class="com.it.factory.UserDaoFactoryBean2"/>
<!-- 配置实例工厂Bean的哪个方法作为工厂方法 -->
<bean id="userDaoImpl2" factory-bean="userDaoFactoryBean2" factory-method="userDaoImpl2">
<constructor-arg name="name" value="小🐱"/>
<constructor-arg name="age" value="18"/>
</bean>1
2
3
4
5
6
7
8// 工厂类
public class UserDaoFactoryBean2 {
// 非静态工厂方法
public UserDaoImpl userDaoImpl2(String name, int age){
// 可以在此编写一些其他逻辑代码
return new UserDaoImpl(name, age);
}
}- 实现FactoryBean规范延迟实例化Bean
1
2
3
4
5
6
7
8
9
10
11
12
13//工厂类
public class UserDaoFactoryBean3 implements FactoryBean<UserDao> {
public UserDao getObject() throws Exception {
return new UserDaoImpl();
}
public Class<?> getObjectType() {
return UserDao.class;
}
}1
<bean id="userDao2" class="com.it.factory.UserDaoFactoryBean3"/>
- 静态工厂方法实例化Bean
Bean 实例化的基本流程
Spring容器在进行初始化时,会将xml配置的的信息(Bean标签)封装成一个BeanDefinition对象,所有的 BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去,Spring框架在对该Map进行遍历,使用反射创建Bean实例对象,创建好的Bean对象存储在一个名为singletonObjects的Map集合中,当调用getBean方法时则最终从该Map集合中取出Bean实例对象返回。
自定义命名空间的解析过程
解决循环引用问题:三级缓存
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 小狼的学习笔记!
评论