Bean的生命周期: bean的创建 ---》初始化 --- 》销毁的过程 容器来管理Bean的生命周期;我们可以自定义初始化和销毁方法;容器在进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法 构造(对象创建) 单实例:在容器启动的时候创建对象 多实例:在每次获取的时候创建对象 初始化: 对象创建完成,并赋值好,调用初始化方法。。。 销毁: 单实例:容器关闭的时候 多实例:容器不会管理这个Bean;容器不会调用销毁方法 1、指定初始化和销毁方法(第一种方式) 通过@Bean指定init-method和destory-method= " "(在xml文件的bean中加入这个两个初始化和销毁方法,并且必须没有参数,而且可以抛任何异常,以前的方式)
通过类来创建指定的初始化方法和销毁方法(一般在配置数据源初始化的是还要做很多事情,以及销毁的时候也需要做一些列的操作就可以使用这个方式来配置)
把这个Car类注册到IOC容器中变成一个Spring的Bean组件
测试:通过创建一个AnnotationConfigApplicationContext对象(也就是第一步,创建一个IOC容器),把MainConfigOfLifeCycle这个类放进去查看这Bean组件
通过注解@Bean把我们指定的Car类里面的init和detory方法通过initMethod="init",destoryMethod="detory"来匹配,这两个创建和销毁的方法必须是对应Car里面的方法对应的名字
在启动容器测试:
在多实例的情况下,Bean是不进行销毁的:
在获取的时候才创建对象:applicationContext.getBean("car")调用这方法的时候才能创建对象,也不会销毁
2)、第二种方式:通过让Bean实现 Spring提供了其中一个接口`InitializingBean`接口(初始化逻辑),里面的方法表示属性设置完成以后调用,也就相当于初始化方法 Spring提供了其中一个接口`DisposableBean`接口(定义销毁逻辑)
定义一个类并实现InitializingBean和DisposableBean这两个接口和里面的方法,也就是初始化和销毁的方法,
并通过@Component注解注册到IOC容器中
通过扫描的方式把组件扫描到并注册到IOC容器
测试:
3)、第三种方式:可以使用JSR250标准
@PostConstruct注解:等这些Bean都装配完成以后来执行一些初始化的方法(对象创建,属性赋值等)来执行标注的这个注解进行初始化
@PreDestory注解:在这些bean在被移除之前,回调和通知,也就是一出之前给我们一个通知,也就是容器在销毁之前会进行调用通知我们执行销毁工作
先定义一个类并通过@Compnent注解表示这个类
测试:
后置处理器的作用:在Bean初始化前后进行处理工作,打开这个BeanPostProcessor,他是一个接口,他有两个方法,一个是Object postProcessBeforeInitialization(Object bean,String beanName):表示在初始化之前进行后处理工作;还有个方法Object postProcessAfterInitialization(Object bean , String beanName):表示进行初始化之后进行一些后置处理
其中这里的两个参数第一个参数:bean是表示容器帮我们创建的实例,还没有初始化和初始化后;beanName就表示在容器中的名字
首先自定义一个MyBeanPostProcessor类实现BeanPostProcessor这个接口,表示这个类在初始化前后进行处理,并实现里面的两个方法,并标注@Component注解让它工作:
其中这两个方法的返回值可以是返回我们要用的bean实例,也可以是返回他原来的对象或者把传进来的对象进行包装之后返回,这里直接返回bean
测试:
遍历的倒容器中所有的BeanPostProcessor;挨个执行beforeInitialization
一旦返回null,跳出ofr循环,不会执行后面的BeanPostProcessor.PostProcessorsBeforeInitialization
BeanPostProcessor原理:
populateBean(beanName,mbd,instanceWrapper);//给bean进行属性赋值
initializationBean{
applyBeanPostProcessorBeaforeInitialzation(warpperBean,beanName);初始化前处理
invokeInitMethods(beanName,warppedBean,mbd);执行自定义初始化
appliyBeanPostProcessorAfterInitialization(warppedBean,beanName); //初始化后处理
}
生命周期-BeanPostProcessor在Spring底层的应用
Spring底层对BeanPostProcessor的使用:
bean的赋值,注入其他组件,@Autowired,生命周期注解功能,@Async,xxx都是用这个BeanPostProcessor来完成的
自动装配:
Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值
1)、@Autowired:自动注入:
①、默认优先按照类型去容器中找对应的组件,applicationConext.getBean(BookDao.class)
②、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找:applicatyionContext.getBean("bookDao")
如何改成第二个呢?
修改我们选择注入的属性名就可以修改成功我们要注入的bookDao2
③、@Qualifer(“bookDao”):使用@Qualifer指定需要装配的组件的id而不是使用属性名
④、只要是标注了自动装配,默认一定要将属性赋值好否则就会报错noSuchAutowriedClass;
可以使用@Autowired(required=false)来表示告诉Spring容器能装上的就装,装不上的就不装
⑤、@Primary:让Spring进行自动装配的时候,默认是用首选的Bean,也就是标注这个注解的组件告诉Spring容器存在多个,并让Spring容器在自动装配的时候首选来装配用了@Primary注解的这个组件,(和属性名没有关系)
也可以继续使用@Qualifer指定需要装配的bean的名字
@Resource:Java规范,可以和@Autowired一样,实现自动装配功能,默认是按照组件名称进行和装配的
没有支持@Primary功能没有支持@Autowired(reqiured=flase);
按照@Resource(name=“bookDao2”)按照名字来装配
@Inject:
需要导入javax.inject的包和Autowired的功能一样,没有required=flase的功能
@Autowired:Spring定义的;@Resource、@Inject都是Java规范
AutowiredAnotationBeanProcessor:解析完成自动装配功能
自动装配方法、构造器位置的自动装配3)、@Autowired:构造器、参数、方法、属性等使用的方式;
都是从容器中获取组件的值
@Bean+方法参数;参数从容器中获取参数组件的值,默认不写@Autowired效果是一样的
(如果组件中只有一个有参构造器,这个有参构造器的@Autowired可以省略,参数位置的组件还是可以自动从容器中获取)
添加注解@ Component在Class类上,默认加在IOC容器中的组件,容器启动会调用无参构造器创建对象,在进行初始化赋值等操作,这里没写有参的构造器,所以使用boss默认的无参构造器
Boss类中有参构造器注入,构造器要用的组件,都是从容器中获取
调用了Boss类中的有参构造器创建对象,而且有参构造器中的Car跟容器中的Car也一样
【标注在方法位置】:@Bean+方法参数;参数从容器中获取参数组件的值,默认不写@Autowired效果是一样的
在另外的配置类里面注册Color组件到IOC容器中
下面测试boss里面的Car和Color里面的Car内存地址是否相同?
4)、自定义组件想要使用Spring容器底层的一些组件(ApplicationConext,BeanFactory ,xxx);自定义组件实现Aware;在创建对象的时候,会调用接口规定的方法注入相关的组件;Aware;
把Spring底层一些组件注入到自定义的Bean中;
xxxAware:功能使用xxxProcessor;每一个xxxAware都有它对应的xxxProcessore
ApplicationContextAware ==》 ApplicationContextAwareProcessor
Aware下的子类全部接口
编写一个类来继承一些接口并实现里面的方法
private ApplicationContext applicationContext;表示保存的IOC容器到这里方便拿来使用,也就是IOC容器
测试结果:
Spring是怎么给Red类中把application注入进来的?
IOC(applicationContext)已经传过来到这个实现的方法里面,里面的这个参数就是application,包含了很多东西
进入到ApplicationContextAwareProcessor类里面调用了这个方法postProcessorBeforeInitialization里面的一个final Object bean 就是我们定义的Red类,里面包含了这个容器的application,也就是这个Bean就是我们定义的Red类
通过判断是实现了那个接口
通过逻辑判断执行invokeAwareInterfaces(bean),把我们写的Red类穿进去做逻辑操作
这个bean就是Red对象,然后判断这个对象是哪个接口下面的,如果是就判断是那一个Aware,是的话就通过setXXX来注入
这里我们实现的是这个接口,接下来就把我们这个bean转成ApplciationContextAware并调用setApplication这个方法把这个(this.applicationContext)搞进去
调用setApplicationContext把IOC传入进来,那么这个bean在初始化的时候利用后置处理器判断这个Bean是ApplicationContextAware,调用Red里面实现接口的setApplicationContext方法把组件传入过来。
这就是Aware原理,Spring底层组件的注入以及原理
Profile:
Spring为我们提供的可以根据当前环境,动态激活和切换一系列组件的功能
开发环境、测试环境、生产环境
数据源:开发环境中数据源连向A数据库的,测试环境中用测试环境的时候在不改动源代码的情况下数据源连向B数据库,最后项目上线连向C数据库 (/A)(/B)(/C)
数据源添加注册
配置文件:



