1 Spring
1.1 beanFactory和ApplicationContext
1.1 1beanFactory
BeanFactory 是字面意思是“Bean 工厂”,那么顾名思义“Bean 工厂”就是用来生产 Bean 或者是用来存放 Bean 的吗?
实际上 BeanFactory
是一个 Spring IoC 容器
。
使用beanFactory完成了ioc思想的实现,下面去实现一下Di依赖注入:
- 定义UserDao接口及其UserDaoImpl实现类
- 修改UserServiceImpl代码,添加一个setUserDao(UserDao userDao)用于接收注入对象
- 修改beans.xml配置文件,在UserDaoImpl的中嵌入配置注入;
- 修改测试代码,获得UserService时,setUserService方法执行注入操作
<bean id="userService" class="com.bjpowernode.impl.UserServiceImpl">
<property name="userDao" ref="userDao"/>
</bean>
<bean id="userDao" class="com.bjpowernode.impl.UserDaoImpl"></bean>
</beans>
public class UserServiceImpl implements UserService {
public void setUserDao(UserDao userDao){
System.out.println("注入"+userDao);
}
}
public class UserDaoImpl implements UserDao {
}
public class BeanFactory {
public static void main(String[] args) {
DefaultListableBeanFactory beanFactory=new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader=new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions("bean.xml");
UserService userService = (UserService) beanFactory.getBean("userService");
System.out.println(userService);
UserDao userDao = (UserDao) beanFactory.getBean("userDao");
System.out.println(userDao);
}
}
1.1.2 ApplicatonContext
ApplicationContext成为Spring容器,内部封存了BeanFactor,比BeanFactor功能更丰富更强大,使用ApplicationContext进行开发时,xml配置文件的名称习惯写成applicationContext.xml
public class ApplicationContextTest {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("bean.xml");
UserService userService = (UserService) applicationContext.getBean("userService");
System.out.println(userService);
}
}
1.1.3 BeanFactory和ApplicationContext的关系
- BeanFactor是Spring的早期接口,成为Spring的bean工厂,ApplicationContext是后期更加高级的接口,成为Spring容器
- ApplicationContext在BeanFactor基础上对功能进行了扩展,例如:监听功能,国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装
- Bean创建的主要逻辑和功能都被封装在BeanFactory,ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内容还维护着BeanFactory的引用,所以,ApplicationContext与BeanFactor既有继承关系,又有融合关系
- Bean的初始化实际不同,原始BeanFactor是在首次调用getBean时才进行Bean的创建,而ApplicationContext则是配置文件加载,容器一创建就将Bean都实例化并初始化好
1.2 实例化bean的方式
1.2.1 构造方法实例化bean
<bean id="bookDao" name="dao dao1 dao2 bookDao2" class="org.example.dao.impl.BookDaoImpl" scope="prototype" />
public class App2 {
public static void main(String[] args) {
// 方式一
//3.获取IoC容器
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
}
}
1.2.2 静态构造方法实例化bean
<bean id="orderDao" class="org.example.factory.OrderDaoFactory" factory-method="getOrderDao"/>
public class OrderDaoFactory {
// 方式二:静态方法
public static OrderDao getOrderDao(){
return new OrderDaoimpl();
}
}
1.2.3动态构造方法实例化bean
<bean id="OrderDao" class="org.example.factory,OrderDaoFacyor" factory-bean="orderFactory" factory-method="getorderDao"/>
public class OrderDaoFactory {
// 方式三:工厂实例化
public OrderDao getorderDao(){
return new OrderDaoimpl();
}
}
1.2.4使用FactoryBean实例化bean
<bean id="orderdao" class="org.example.factory.OrderDaoFactoryBean"/>
public class OrderDaoFactoryBean implements FactoryBean<OrderDao> {
// 方式四:代替原始实例工厂中创建的方法
public OrderDao getObject() throws Exception {
return new OrderDaoimpl();
}
public Class<?> getObjectType() {
return OrderDao.class;
}
//控制是否单例
public boolean isSingleton() {
return false;
}
}
1.2.5 Bean的作用域
-
singleton,每次注⼊只会创建⼀次
-
prototype,每次注⼊都会创建⼀次
-
request,每次请求都会创建⼀次
-
session,每个session内只会创建⼀次,随着session过期
-
global_session,全局session只会创建⼀次,随着全局session过期
1.3 Spring应用
1.3.1 Bean实例化的基本流程
- 加载xml配置文件,解析获取配置中的每个的信息,封装成一个个的BeanDefinition对象
- 将BeanDefinition存储在一个名为beanDefinitionMap的Map<String,BeanDefinition>
- ApplicationContext底层遍历beanDefinitionMap,创建Bean实例对象
- 创建好的Bean实例对象,被存到一个名为singletonObjects的Map<String,Object>中
- 当执行applicationContext.getBean(beanName)时,从singletonObject去匹配Bean实例返回
1.3.2 工厂后处理器
Spring的后处理器是Spring对外开发的重要扩展点,允许我们介入Bean的整个实例化流程中来,以达到动态注册BeanDefinition,动态修改BeanDefinition,以及动态修改Bean的作用.Spring主要有两种后处理器:
- BeanFactoryPostProcessor:Bean工厂后处理器,在BeanDefinitionMap填充完毕,Bean实例化之前执行;
- BeanPostProcessor:Bean后处理器,一般在Bean实例化之后,填充到单例池singletonObjects之前执行
1.3.3 BeanFactoryPostProcessor
BeanFactoryPostProcessor是一个接口规范,实现了该接口的类只要交由Spring容器管理的话,那么Spring就会回调接口的方法,用于对BeanDefinition注册和修改的功能。
BeanFactoryPostProcessor定义如下
public interface BeanFactoryPostProcessor{
void postProcessBeanFactor(ConfigurableListableBeanFactor beanFactor){
}
}
//修改功能
public class MyBeanFactory implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("beanDefinitionMap填充完毕后回调该方法");
//不会把整个map全部拿到 但是可以根据名字拿到map其中的数据
BeanDefinition userService = beanFactory.getBeanDefinition("userService");
userService.setBeanClassName("com.bjpowernode.UserDaoImpl");
}
}
//bean的新增
public class MyBeanFactory implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("beanDefinitionMap填充完毕后回调该方法");
//先创建一个beanDefinition对象
BeanDefinition beanDefinition=new RootBeanDefinition();
beanDefinition.setBeanClassName("com.bjpowernode.dao.UserServiceImpl");
//DefaultListableBeanFactory是ConfigurableListableBeanFactory的一个子类 这样可以实现bean的新增
DefaultListableBeanFactory defaultListableBeanFactory=(DefaultListableBeanFactory) beanDefinition;
defaultListableBeanFactory.registerBeanDefinition("userServiceImpl",beanDefinition);
}
}
1.3.4 BeanDefinitionRegistryPostProcessor
//BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
public class ApplicationContextTest implements BeanDefinitionRegistryPostProcessor {
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
//先执行这个
//注册新增bean对象
}
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
//在执行这个
//修改bean对象功能
}
}
1.3.5 Bean后处理器-BeanPostProcessor
Bean被实例化后,到最终缓存到名为singletonObjects单例池之前,中间会经过Bean的初始化过程,例如:属性的填充,初始化方法init的执行等,其中有一个对外进行扩展的点BeanPostProcessor,我们称为Bean后处理.跟上面的Bean工厂后处理器相似,它也是一个接口,实现了该接口并被容器的BeanPostProcessor,会在流程节点上被Spring自动调用
public class MyBeanPostProcessor implements BeanPostProcessor {
//bean创建之前按
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return null;
}
//中间会有类的初始化方法
//bean创建之后
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return null;
}
}
1.4 Spring Bean的生命周期
SpringBean的生命周期是从Bean实例化之后,即通过反射创建处对象之后,到Bean成为一个完整对象,最终存储到单例池中,这个过程被称为SpringBean的生命周期。Spring Bean的生命周期大体上分为三个阶段:
- Bean的实例化阶段:Spring框架会取出BeanDefinition的信息进行判断当前Bean的范围是否是singleton的,是否不是延迟加载的,是否不是FactorBean等,最终将一个普通的singleton的Bean通过反射进行实例化;
- bean的初始化阶段:Bean创建之后还仅仅是个"半成品",还需要对Bean实例的属性进行填充,执行一些Aware接口方法,执行BeanPostProcessor方法,执行InitializingBean接口的初始化方法,执行自定义初始化init方法等.该
- Bean的完成阶段:经过初始化阶段,Bean就成为了一个完整的Spring Bean,被存储到单例池singletonObject中去了,即完成了Spring Bean的整个生命周期
1.4.1Spring Bean初始化过程
- Bean实例的属性填充
- Aware接口属性注入
- BeanPostProcessor的before()方法回调
- InitializingBean接口的初始化方法回调
- 自定义初始化方法init回调
- BeanPostProcessor的after()方法回调
1.4.2 Bean的属性填充
- 注入普通属性,String,int或存储基本类型集合时,直接通过set方法的反射设置进去;
- 注入单向对象引用属性时,从容器中getBean获取后通过set方法反射进去,如果容器中没有,则先创建被注入对象Bean实例(完成整个生命周期)后,在进行注入操作
- 注入双向对象引用属性时,比较复杂
1.4.3 三级缓存
//第1级缓存 用于存放 已经属性赋值、完成初始化的 单列BEAN
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
//第2级缓存 用于存在已经实例化,还未做代理属性赋值操作的 单例BEAN
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
//第3级缓存 存储创建单例BEAN的工厂
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16)
- UserService实例化对象,但尚未初始化,将UserService存储到三级缓存
- UserService属性注入,需要UserDao,从缓存中获取,没有UserDao;
- UserDao实例化对象,但尚未初始化,将UserDao存储到三级缓存
- UserDao属性注入,需要UserService,从三级缓存获取UserService,UserService从三级缓存移入二级缓存
- UserDao执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存
- UserService注入UserDao
- UserService执行其他生命周期过程,最终成为一个完成Bean,存储到一级缓存,删除二三级缓存
1.3.4 常用的Aware接口
Aware接口是一种框架辅助属性注入一种思想,其他框架中也可以看到类似的接口.框架具备高度封装性,我们接触到的一个都是业务代码,一个底层功能API不能轻易的获取到,但是这不意味着永远用不到这些对象,如果用到了,就可以使用框架提供的类似Aware接口,让框架给我们注入该对象
总结
1.4 Spring注解
//@Component衍生注解 @Repository在dao层类上使用 @Service @Controller
@Component("userDao")
//作用范围注解
@Scope("singleton")
//拖延加载
@Lazy(false)
public class UserDaoImpl implements UserDao {
public UserDaoImpl() {
}
//初始化方法注解
@PostConstruct
public void init(){
System.out.println("userDao的初始化方法");
}
//销毁方法注解
@PreDestroy
public void destroy(){
System.out.println("userDao的销毁方法");
}
}