Spring bean容器
Spring Bean 容器(spring 容器(container) 管理 bean的整个生命周期)
Spring IOC 控制反转 DI 依赖注入
Spring AOP 面向切片编程 Aspect Oriented Programing
Bean配置信息定义了Bean的实现及依赖关系,Spring容器根据各种形式的Bean配置信息在容器内部建立Bean定义注册表,然后根据注册表加载、实例化Bean,并建立Bean和Bean的依赖关系,最后将这些准备就绪的Bean放到Bean缓存池中,以供外层的应用程序进行调用。
从上图可以清楚的看出 Bean 实现类,Bean配置信息,Spring容器,和Bean调用者之间的关系
Spring应用中,应用对象生存于容器(container, spring 容器)中,spring负责创建对象并装配它们,配置它们并管理它们的整个生命周期,从生存到死亡——new到finalize() ( GC 回收不用的对象)
spring容器可归为两类
bean工厂(org.springframework.beans.factory.BeanFactory) 提供简单DI支持
应用上下文(org.springframework.context.ApplicationContext)基于BeanFactory构建,并提供框架服务,如配置解析
实例化---->填充属性---->调用BeanNameAware setBeanName()---->调用BeanFactoryAware setBeanFactory()---->调用ApplicationContextAware setApplicationContext()---->调用BeanPostProcessor的预初始化方法---->调用InitializingBean的afterPropertiesSet()方法---->调用自定义的初始化方法---->调用BeanPostProcessor的初始化后方法
至此bean已经可以使用
当容器关闭 ——>调用DisposableBean的destroy()方法——>调用自定义销毁方法——>bean销毁
详细过程:
1.Spring首先对bean进行实例化、
2.Spring将值和bean的引用注入到bean对应的属性当中
3.如果bean实现了BeanNameAware接口,Spring将bean的ID传递给setBeanName()
4.如果bean实现了BeanFactoryAware接口,Spring将调用setBeanFactory()方法,将BeanFacotry容器实例传入
5.如果bean实现了ApplicationContextAware接口,Spring将调用setApplicationContext()方法,将bean所在的应用上下文的引用传入进来
6.如果bean实现了BeanPostProcessor接口,Spring将调用他们的postProcessBeforeInitialization()
7.如果bean实现了InitializingBean接口,Spring将调用他们的afterPropertiesSet()方法
8.如果bean实现了BeanPostProcessor接口,Spring将调用它们的postProcessAfterInitialization()
9.Bean准备就绪,驻留在spring应用上下文
10.如果bean实现了DisposableBean接口,Spring将调用它的destroy()方法,同样,如果bean使用destroy-method声明了销毁方法,该方法也会被调用
Bean注入
Bean注入
1、属性注入(setter 注入)
2、构造函数注入
3、工厂方式注入
4、使用注解的方式注入
属性注入
属性注入即通过setXxx()方法注入Bean的属性值或依赖对象,由于属性注入方式具有可选择性和灵活性高的优点,因此属性注入是实际应用中最常采用的注入方式。
属性注入要求Bean提供一个默认的构造函数,并为需要注入的属性提供对应的Setter方法。Spring先调用Bean的默认构造函数实例化Bean对象,然后通过反射的方式调用Setter方法注入属性值。
构造方法注入
使用构造函数注入的前提是Bean必须提供带参数的构造函数。
工厂方法注入
package com.baobaotao.ditype;
public class CarFactory {
public Car createHongQiCar(){
Car car = new Car();
car.setBrand("红旗CA72");
return car;
}
public static Car createCar(){
Car car = new Car();
return car;
}
}
使用注解的方式注入
使用@Autowired进行自动注入
Spring通过@Autowired注解实现Bean的依赖注入
Spring即使找不到匹配的Bean完成注入也不用抛出异常,那么可以使用@Autowired(required=false)进行标注:
@Autowired(required=false)
private LogDao logDao;
如果容器中有一个以上匹配的Bean时,则可以通过@Qualifier注解限定Bean的名称
//①注入名为userDao,类型为UserDao的Bean
@Autowired
@Qualifier("userDao")
private UserDao userDao;
对类方法进行标注
@Autowired可以对类成员变量及方法的入参进行标注,下面我们在类的方法上使用@Autowired注解
@Autowired
public void init(@Qualifier("userDao")UserDao userDao,LogDao logDao){
System.out.println("multi param inject");
this.userDao = userDao;
this.logDao =logDao;
}
如果一个方法拥有多个入参,在默认情况下,Spring自动选择匹配入参类型的Bean进行注入。Spring允许对方法入参标注@Qualifier以指定注入Bean的名称
在以上例子中,UserDao的入参注入名为userDao的Bean,而LogDao的入参注入LogDao类型的Bean。
补充:
Spring还支持@Resource和@Inject注解,这两个标准注解和@Autowired注解的功能类型,都是对类变量及方法入参提供自动注入的功能。@Resource要求提供一个Bean名称的属性,如果属性为空,则自动采用标注处的变量名或方法名作为Bean的名称。
如果@Resource未指定"car"属性,则也可以根据属性方法得到需要注入的Bean名称。可见@Autowired默认按类型匹配注入Bean,@Resource则按名称匹配注入Bean。
@Autowired
private LogDao logXXXDao; //按类型注入 ByType
@Resource
private UserDao userDao; // 按名称注入 ByName
而@Inject和@Autowired一样也是按类型匹配注入的Bean的,只不过它没有required属性。可见不管是@Resource还是@Inject注解,其功能都没有@Autowired丰富,因此除非必须,大可不必在乎这两个注解。
关于Autowired和@Resource
1.@Autowired注入是按照类型注入的,只要配置文件中的bean类型和需要的bean类型是一致的,这时候注入就没问题。但是如果相同类型的bean不止一个,此时注入就会出现问题,Spring容器无法启动。
2.@Resourced标签是按照bean的名字来进行注入的,如果我们没有在使用@Resource时指定bean的名字,同时Spring容器中又没有该名字的bean,这时候@Resource就会退化为@Autowired即按照类型注入,这样就有可能违背了使用@Resource的初衷。所以建议在使用@Resource时都显示指定一下bean的名字@Resource(name="xxx")
参考:https://www.cnblogs.com/wuchanming/p/5426746.html