Spring IOC容器回顾
Spring IOC容器启动方式
- 纯XML方式启动:bean信息定义全部配置在xml中
- javaSE应用:
//javaSE两种方式
ApplicationContext context = new ClassPathXmlApplicationContext("path");
ApplicationContext context1 = new FileSystemXmlApplicationContext("path");
` - javaWeb应用:
ContextLoaderListener
监听器去加载xml
- javaSE应用:
- xml+注解混合:一部分存在于bean中一部分存在于注解中,一般自己开发的使用注解,第三方jar包使用xml加到容器中
- 纯注解模式:所有的bean都存在于注解定义
- javaSE应用:
//AnnotationConfigApplicationContext可以传入bean工厂,也可以传入主配置类class
ApplicationContext context = new AnnotationConfigApplicationContext(); - javaWeb应用:
ContextLoaderListener
监听器去加载注解配置类BeanFactory与AppliactionContext关系
BeanFactory
是SpringIOC容器的顶级接口,只是用来定义一些基础功能,是SpringIOC的基础容器ApplicationContext
是BeanFactory
的一个子接口,是SpringIOC的高级接口。
- javaSE应用:
BeanFactory主要是用于管理bean,而AppliactionContext除了管理bean的作用,还支持了配置文件的加载(XML、java配置类)、国际化支持。这里体现了Spring的设计巧妙
Spring IOC容器创建bean的三种方式
- 使用无参构造器(推荐)
<bean id="connectUtils" class="com.lagou.edu.utils.ConnectionUtils"/>
- 该方式主要是为了我们自己new的对象加到SpringIOC容器中进行管理,使用静态方法
- 首先需要创建一个静态方法,静态方法返回值就是加到容器中的对象
public class ConnectUtilsFactory {
public static ConnectionUtils getConnectionUtils(){
return new ConnectionUtils();
}
} - 将该方法通过配置加到容器中,
factory-method
就是静态方法<bean id="connectUtils" class="com.lagou.edu.factory.ConnectUtilsFactory" factory-method="getConnectionUtils"/>
- 首先需要创建一个静态方法,静态方法返回值就是加到容器中的对象
- 使用实例化方法将对象加入到容器中
- 首先我们需要创建实例化方法
public class ConnectUtilsFactory {
public ConnectionUtils getConnect(){
return new ConnectionUtils();
}
} - 将
ConnectUtilsFactory
加到容器中<bean id="connectUtilsFactory" class="com.lagou.edu.factory.ConnectUtilsFactory"/>
- 然后在创建
connectUtils
时,使用之前创建的connectUtilsFactory
中获取到对象<bean id="connectUtils" factory-bean="connectUtilsFactory" factory-method="getConnect"/>
bean的作用范围及生命周期
配置文件中scope指定bean的作用范围
在xml中创建bean的时候可以通过scope
定义bean的作用范围Scope 作用 singleton 单例,IOC容器中只有一个该类的对象 prototype 原型,每次使用该类的对象(getBean),都返回给你一个新的对象,Spring只创建对象,不管理对象 request 针对web而言,每次请求都会返回一个对象 session 针对web而言,每一个session会产生一个对象 application 针对web而言,每一个 ServletContext
是一个对象websocket 针对webSocket而言,每有一个webSockert就会产生一个对象
- 首先我们需要创建实例化方法
如果scope缺失,默认值为singleton
bean的生命周期
参考[https://www.cnblogs.com/javazhiyin/p/10905294.html]
Spring在创建bean的过程是非常复杂的,这里仅仅简单的介绍一下bean创建的几个重要的环节
- Spring启动之后,查找并加载需要被Spring管理的bean,进行Bean的实例化
- Bean实例化后将Bean的引用和值注入到Bean的属性中
- 如果Bean实现了
BenaNameAware
接口的话,Spring将Bena的id传递给setBeanName
方法 - 如果Bean实现了
BeanFactoryAware
接口的话,Spring将调用setBeanFactory()
方法,将BeanFactory容器实例传入 - 如果Bean实现了
ApplicationContextAware
接口的话,Spring将调用Bean的setApplicationContext()
方法,将bean所在应用上下文引用传入进来。 - 如果Bean实现了
BeanPostProcessor
接口,Spring就将调用他们的postProcessBeforeInitialization()
方法,初始化之前调用。 - 如果Bean 实现了
InitializingBean
接口,Spring将调用他们的afterPropertiesSet()
方法。类似的,如果bean使用init-method
声明了初始化方法,该方法也会被调用 - 如果Bean 实现了
BeanPostProcessor
接口,Spring就将调用他们的postProcessAfterInitialization()
方法,初始化之后调用。 - 此时,Bean已经准备就绪,可以被应用程序使用了。他们将一直驻留在应用上下文中,直到应用上下文被销毁。
- 如果bean实现了
DisposableBean
接口,Spring将调用它的destory()
接口方法,同样,如果bean使用了destory-method
声明销毁方法,该方法也会被调用。Spring DI依赖注入配置
- set方法注入:set方法注入使用的是
property
标签,如果注入的是另外一个bean那么使用ref属性,如果注入的是普通值没那么使用的是value属性 - 构造函数注入 使用
constructor-arg
标签,使用name或者index指定注入的是哪个参数需要注入
Spring IOC高级特性
lazy-init 延迟加载
延迟加载指的是singleton bean
对象的延迟加载,或者说是延迟创建。
ApplicationContext容器的默认行为是在启动服务器时将所有singleton bean提前进行实例化。提前实例化意味着作为初始化过程中的一部分,ApplicationContext实例会创建并配置所有的singleton bean。
是否对bean进行延迟加载,是通过lazy-init
属性进行控制的,默认为false。修改为true时,此bean就会设置为延迟实例化。
- 使用xml时,
<!--针对全局bean lazy-init的默认属性修改 default-lazy-init="true"-->
<beans default-lazy-init="true" xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<!--针对单独的bean-->
<bean id="connectUtils" class="com.lagou.edu.utils.ConnectionUtils" lazy-init="true"/> - 使用注解方式
public class connectUtils {}应用场景
- 开启延迟加载一定程度上可以提高容器启动和运转性能
- 对于不常使用的Bean 设置延迟加载,这样偶尔使用的时候再加载。不必要从一开始该Bean就占用资源
FactoryBean与BeanFactory
BeanFactory
BeanFactory是容器的顶级接口,定义了容易的一些基础行为,负责生产和管理Bean的一个工厂,具体使用它下main的子接口类型,比如AppliactionContext。
FactoryBean
Spring中Bean有两种,一种是普通Bean,一种是工厂Bean(FactoryBean),FactoryBean可以生成某一种类型的Bean实例(返回给我们),也就是说我们可以借助它自定义Bean的创建过程
//可以让我们自定义Bean的创建过程(完成复杂bean的定义) |
使用方法
首先我们需要定义一个需要注入到Spring容器中的Bean
public class Company {
private String name;
private String address;
private int scale;
...get/set...
}然后我们创建一个工厂类,继承
FactoryBean
接口,该接口主要目的就是生产Company
public class CompanyFactoryBean implements FactoryBean<Company> {
public Company getObject() throws Exception {
//创建复杂对象Company
Company company = new Company();
company.setAddress("我不知道");
company.setName("my");
company.setScale(1);
return company;
}
public Class<?> getObjectType() {
return Company.class;
}
/**
* 是否单例
* @return
*/
public boolean isSingleton() {
return true;
}
}我们需要将该类(CompanyFactoryBean)注册到Spring中
<bean id="companyBean" class="com.zenshin.spring.CompanyFactoryBean"/>
我们吧工厂类加入后,使用
companyBean
就可以从spring中获取Company
;类实例从容器中取出该类
public void test1(){
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
//获取Company
Object companyBean = context.getBean("companyBean");
System.out.println(companyBean);
//加入& 获取CompanyFactoryBean
Object companyFactoryBean = context.getBean("&companyBean");
System.out.println(companyFactoryBean);
}
后置处理器
Spring提供了两种处理Bean的扩展接口,分别为BeanPostProcessor
和BeanFactoryPostProcessor
,两者在使用上是有所区别的。
在BeanFactory初始化后可以使用BeanFactoryPostProcessor进行后置处理做一些事情
在Bean对象实例化(并不是Bean的整个生命周期完成)后可以使用BeanPostProcessor进行后置处理做一些事情
BeanPostProcessor
BeanFactoryPostProcessor
Spring源码解析
default boolean isSingleton() {
return true;
}
}