使用应用上下文容器(ApplicationContext)来获取bean的bean的生命周期

来源:互联网 发布:尼克杨数据 编辑:程序博客网 时间:2024/06/04 23:31

前话:初学者的我看了一天教程懵懵懂懂总结一下,大佬看到有错的帮忙指点指点下- - ,我是自学- -

先上我用来测试的全部类以及bean文件还有输出结果:


 PersonService .java

public class PersonService implements BeanNameAware,BeanFactoryAware,ApplicationContextAware,InitializingBean{
private String name;
public String getName() {
System.out.println("getName(String name) 方法被调用");//经测试,这个不会输出
return name;
}
//构造方法
public PersonService() {

System.out.println("'PersonService 的构造方法被实例化");
}
//set方法
public void setName(String name) {
System.out.println("setName(String name) 方法被调用");
this.name = name;
}
//
public void sayHi() {
System.out.println("hi" + name + "-嘴上笑嘻嘻,心中mmp");
}
// 这个方法是接口 BeanNameAware 的方法,获取正在被实例化的bean的id是什么
@Override
public void setBeanName(String arg0) {
// TODO Auto-generated method stub
System.out.println("通过 BeanNameAware的setBeanName获得正在被调用的bean的id是:" + arg0);
}
// 这个方法是接口 BeanFactoryAware的,改方法可以传递bean工厂对象,输出bean文档里面配置了几个bean
@Override
public void setBeanFactory(BeanFactory arg0) throws BeansException {
// TODO Auto-generated method stub
System.out.println("这里是 BeanFactoryAware的setBeanFactory:" + arg0);

}
//ApplicationContextAware接口的方法setApplicationContext;可以获得使用什么方法获取beans容器(xml)的,以及beans容器的名字,以及创建bean工厂的时间
@Override
public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("这里是ApplicationContextAware的setApplicationContext,获得得失-------"+ arg0);
}
//InitializingBean接口的afterPropertiesSet()方法,会获取啥俺不知道
@Override
public void afterPropertiesSet() throws Exception {
// TODO Auto-generated method stub
System.out.println("InitializingBean接口的afterPropertiesSet()方法被调用了");
}
//自定义初始化方法myInit
public void myInit(){
System.out.println("自定义初始化方法myInit被调用了");
}
//自定义销毁bean的方法,bean活得太久了,该死了!!!!!不过资源会释放,但是输出的话不会输出,因为容器已经关闭了
public void myDestroy(){
System.out.println("bean已死,有事烧纸,资源已释放,要的自己上,不过你看不见我这句话,因为容器关闭啦");
}
}


BeanPostProcessor.java

//实现BeanPostProcessor接口的类
//BeanPostProcessor-一个后置处理器,这个是要配置到bean里面,xml文件里面的,一旦配置进xml里面,那么xml里面的bean在加载时一定会调用这个

public class MyBeanPostProcessor implements BeanPostProcessor{
//postProcessBeforeInitialization和postProcessAfterInitialization就想过滤器一样
//这是后初始化方法
@Override
public Object postProcessAfterInitialization(Object arg0, String arg1)
throws BeansException {
// TODO Auto-generated method stub
System.out.println("BeanPostProcessor接口的postProcessAfterInitialization函数被调用");
System.out.println(arg0+"这个对象被调用的结束时间是:"+new java.util.Date());//输出正在被实例化加载的bean调用这个函数的时间
return arg0;//这个返回的是正在被实例化加载的bean的名字
}
//这是前初始化方法
@Override
public Object postProcessBeforeInitialization(Object arg0, String arg1)
throws BeansException {
// TODO Auto-generated method stub
System.out.println(arg0+"这个对象被调用的时间是:"+new java.util.Date());
System.out.println("BeanPostProcessor接口的postProcessBeforeInitialization函数被调用");
return arg0;
}
}


测试类Demo

public class Demo{
public static void main(String[]args){
ApplicationContext ac = new ClassPathXmlApplicationContext("beanLife/beanLifeDemo.xml");
//当new一个上下文容器(ApplicationContext)后,程序就会加载并实例化bean的scope属性为默认值或者singleton
//的bean,然后会调用以对方法,具体如下
//首先会调用bean配置的类的无参的构造方法
//然后就是调用bean配置的name(<property name="">)所对应的类的相应的setName方法(),
//然后就会马上调用BeanNameAware接口的setBeanName方法去火的正在被调用的bean的id
//接着就会调用 BeanFactoryAware接口的setBeanFactory去获得beans容器中所有的bean
//然后会立马去调用ApplicationContextAware接口的setApplicationContext方法去获得
// 类是通过哪个方法去获得beans容器的(xml文件),以及beans容器(xml文件)的名字,以及创建bean工厂的时间
//然后就会调用beans容器(xml文件)里面配置的后置处理器BeanPostProcessor接口(类似过滤器)(如果没配置就不调用),如果配置了就一定会被调用
// //并且有多少个bean就会被调用多少次,也就是实例化一个bean会马上调用一次,实例化第二个bean也会马上调用一次,以此类推第n个
//后置处理器BeanPostProcessor接口(类似过滤器)---预初始化方法---postProcessBeforeInitialization--先调用
//   ---后初始化方法---postProcessAfterInitialization---后调用
//如果有定义InitializingBean接口,那么postProcessBeforeInitialization调用之后会先调用这个InitializingBean接口的afterPropertiesSet()方法
//然后如果有在bean里面配置自定义的初始化方法,那么在afterPropertiesSet()执行完后,会先调用自定义初始化方法,最后才会调用后置处理器BeanPostProcessor的postProcessAfterInitialization后初始化方法
//然后bean就可以使用了,如楼下

//这个会在全部bean被加载实例化完后才输出
PersonService ps=(PersonService)ac.getBean("personService");
ps.sayHi();


//使用完后就是关闭容器(如果容器关闭了,那么bean就被销毁了,也就是bean的生命结束!death)
//当然销毁bean也可以调用disposableBean接口的destory()方法去销毁,不过不建议
//或者自定义的销毁bean的 方法,同自定义初始化方法类似
}
}


bean文件(xml配置文件)


<beans>
<!-- 这里的没有scope属性,也就是这里是默认的scope属性,默认的scope属性是scope="singleton",说明这个bean在ApplicationContext对象
创建后并且调用的xml文件是这个时,这个bean就会立马被加载实例化-->
<!-- init-method="myInit",自定义初始化方法 -destroy-method="myDestroy"自定义的销毁bean的方法-->
<bean id="personService" init-method="myInit" destroy-method="myDestroy" class="beanLife.PersonService">
<!-- 这里就是注入属性,前提有个set和get方法才能成功 -->
<property name="name">
<value>王尼玛</value>
</property>
</bean>

<!-- 两个bean是证明只要是bean被加载实例化,都会调用 后置处理器BeanPostProcessor的方法-->
<bean id="personService2" class="beanLife.PersonService">
<!-- 这里就是注入属性,前提有个set和get方法才能成功 -->
<property name="name">
<value>王尼玛</value>
</property>
</bean>
<!-- personService2放下面是证明调用(使用)bean会在bean被全部实例化加载完后才能使用(调用) -->

<!-- 配置后置处理器(过滤器) -->
<bean id="myBeanPostProcessor" class="beanLife.MyBeanPostProcessor">
</bean>
</beans>


输出结果

'PersonService 的构造方法被实例化
setName(String name) 方法被调用
通过 BeanNameAware的setBeanName获得正在被调用的bean的id是:personService
这里是 BeanFactoryAware的setBeanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@6d8a00e3: defining beans [personService,personService2,myBeanPostProcessor]; root of factory hierarchy
这里是ApplicationContextAware的setApplicationContext,获得得失-------org.springframework.context.support.ClassPathXmlApplicationContext@5910e440: startup date [Mon Aug 28 23:23:12 CST 2017]; root of context hierarchy
beanLife.PersonService@31610302这个对象被调用的时间是:Mon Aug 28 23:23:14 CST 2017
BeanPostProcessor接口的postProcessBeforeInitialization函数被调用
InitializingBean接口的afterPropertiesSet()方法被调用了
自定义初始化方法myInit被调用了
BeanPostProcessor接口的postProcessAfterInitialization函数被调用
beanLife.PersonService@31610302这个对象被调用的结束时间是:Mon Aug 28 23:23:14 CST 2017
'PersonService 的构造方法被实例化
setName(String name) 方法被调用
通过 BeanNameAware的setBeanName获得正在被调用的bean的id是:personService2
这里是 BeanFactoryAware的setBeanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory@6d8a00e3: defining beans [personService,personService2,myBeanPostProcessor]; root of factory hierarchy
这里是ApplicationContextAware的setApplicationContext,获得得失-------org.springframework.context.support.ClassPathXmlApplicationContext@5910e440: startup date [Mon Aug 28 23:23:12 CST 2017]; root of context hierarchy
beanLife.PersonService@71318ec4这个对象被调用的时间是:Mon Aug 28 23:23:14 CST 2017
BeanPostProcessor接口的postProcessBeforeInitialization函数被调用
InitializingBean接口的afterPropertiesSet()方法被调用了
BeanPostProcessor接口的postProcessAfterInitialization函数被调用
beanLife.PersonService@71318ec4这个对象被调用的结束时间是:Mon Aug 28 23:23:14 CST 2017
hi王尼玛-嘴上笑嘻嘻,心中mmp



总结:一般情况下就是这样的:实例化bean(bean生命开始),然后用set方法设置属性,如果有需要也会调用后置处理器BeanPostProcess,然后就是使用bean了,使用完后就关闭容器(bean生命结束)。

但是真要说的话不止这些,就像我上面写的测试一样,真要说的话有十多步:

1-实例化bean,bean生命开始

2-设置属性值

3-调用BeanNameAware接口的setBeanName方法(获得目前正在实例化的bean的ID)

4-调用beanFactoryAware接口的setBeanFactory方法(获得bean容器里面的所有的bean)

5-调用ApplicationContext接口的setApplicationContext方法(获得测试方法是通过什么方法获取bean容器(xml)文件的,以及获取bean容器(xml)的文件名,以及bean工厂的启用时间)

6-1调用后置处理器BeanPostProcessor接口(类似过滤器)的预初始化方法postProcessBeforeInitialization

6-2-在bean容器中配置BeanPostProcessor的bean

7-调用InitalizingBean的afterPropertiesSet方法()------这是干嘛的俺不知道

8-(如果需要)自定义初始化方法

9-调用后置处理器BeanPostProcessor接口(类似过滤器)的后初始化方法postProcessAfterInitialization

10-现在,可以使用bean了

11-使用完后关闭容器,bean销毁,bean的生命结束

12-(如果需要)可以自定义销毁方法

13-结束!


好复杂,不知道我这样子记对不对。各位大牛发现有错希望能帮忙指点下,我是在家自学的,不喜勿喷喜请点赞!



阅读全文
0 0