前言
javaBean
javaBean是java公共组件的标准。起源于Java GUI的可视化编程实现的,所有的组件都需要支持拖拉,那么所有的组件的行为都是一致的。当拖拉组件的时候,就会创建一个改组件的对象,然后进行参数赋值改变组件的属性。 拖拉一个组件等于创建了这个组件的一个对象,在拖拉的时候是无法提供参数的。拖拉之后才能给组件赋值,怎么赋值。
实例化
实例化那么必须是一个类,不是接口,也不能是抽象类
无条件实例化
拖拉完成才能得到真正的坐标,大家不会拖拉之前就设定属性,而是按照原型图,先拖拉在设定属性。所以实例化在前,属性设置在后。如果定义了有参构造函数,那么需要提供参数才能实例化,等于先设定属性,不符合Java GUI的可视化编程中拖拉的规则。组件必须要有一个无参构造方法,可以无条件实例化。
无条件实例化一定有一个无参构造方法,不需要关注其他细节,拉来就可以使用。
变量私有化
其实这个并不是Java GUI的可视化编程里面必须条件,但是因为面向对象设计与面向对象提供封装这个特性,而且变量私有化和封装带来了很多好处,变量私有化成为了javaBean中一个重要的特性
私有化变量通过get/set方法进行操作
当一个组件有很多属性,多个不同属性可以组成一个行为,多个属性出现N中排列组合,是否需要各种排列组合的有参构造方法。
随着时间的推动,需求发生变化,需要添加一个属性,是否出现大量的新的排列组合,需要修改和添加大量的有参构造方法
所以通过get/set的方式,提高了很大的灵活度,扩展度,方便维护
如果某个属性不是提供对外负责,只提供本类或者子类,同包使用,不用与数据传递,可以不提供get/set方法。
总结
Java GUI的可视化编程对组件的定义,对维护,扩展等方面十分友好,很大程度提高了可视化编程效率。等到很多程序员的认可,普及率高,广泛。慢慢成为了javaBean规范。
javaBean规范是整个java体系的基石
javaBean规范是整个java体系的基石
javaBean规范是整个java体系的基石
规范细节
- 普通类,才能实例化。不是接口,也不是抽象类
- 无参构造方法。如果没有定义无参构造方法,在没有任何其他有参构造方法的情况下,javac会在class文件中生产无参构造方法。这点是Javabean最重要的特性,是不可缺少的。
- 变量私有化
- 提供变量操作方法get/set, boolean可以使用前缀未is
- 变量与方法的命令按照驼峰命名法
public class userInfo{
private long uiId;
private String uiName;
public void setUiId(long uiId){
this.uiId = uiId;
}
public long getUiId(){
return this.uiId;
}
public void setUiName(long uiName){
this.uiName = uiName;
}
public long getUiName(){
return this.uiName;
}
}
看看这个类
public class niaocai{
private int ctl = 1;
}
这样也是一个javabean,只是没有set/get。但是因为ctl只是给自己用的
spring的bean
spring的bean其实就参照的ejb的bean,两者从出发点,实现等基本一致,所以占同称bean。已经有了javaBean,为什么还要bean了。在企业需求越来越复杂,造成工程越来越庞大,复杂,脓肿。现有的javabean无法解决问题。所以提出了依赖注入,反转控制的概念。bean是解决依赖注入,反转控制中。
一个框架实现ioc,那么必须提供一个容器,否者无法实现ioc 有容器了,非容器的bean如何想到容器本身的一些bean
看下面有什么问题
public class Niaocai{
private Niao niao;
private Cai cai;
private String daSshen;
public Niaocai(){
init();
}
public init(){
if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
daSshen = "dashen"
}else{
daSshen = "cainiao"
}
}
}
上面是不是在实例化的时候会报错。因为调用init比注入要优选。这个问题怎么解决,大家都给下面的解决方案
public class Niaocai{
private Niao niao;
private Cai cai;
private String daSshen;
public Niaocai(Niao niao , Cai cai){
this.niao = niao;
this.cai = cai;
if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
daSshen = "dashen"
}else{
daSshen = "cainiao"
}
}
}
解决了在实例化的时候,回答javabean的定义中,分析了构造方法弊端。所以需要另外的解决方法
public class Niaocai{
private Niao niao;
private Cai cai;
private String daSshen;
@PostConstruct
public init(){
if(niao.getxxx == xxxx && cai.getXXXX ==xxxx){
daSshen = "dashen"
}else{
daSshen = "cainiao"
}
}
... get/set方法
}
Niaocai niaocai = new Niaocai();
niaocai.setNaio(niao);
niaocai.setCai(cai);
niaocai.init();
从上面的代码,分析到依赖注入与Aware接口参数注入之后会调用初始化方法。当初始化方法执行完,才标识这个bean完成。实例化完成只是javabean完成的标识。
真确理解bean的生命周期
- 实例化
- 依赖注入
- Aware接口参数注入
- 初始化
- 销毁
读者会问,bean的生命周期,怎么仅仅有这些啊。不是还有很多接口。 深入了解下什么是生命周期。生命周期是指一个个体的生老病死。那些接口只是对bean进行监控而已。比如单一个生命之前,会进行检测,出生之后会进行户口登记,死亡会注销户口。这些与个人的生命周期没有关系啊。
bean处理体系
bean处理体系是bean最重要的模块之一,本节只是大概,简单让大家了解bean处理系统。在第五章有专门的章节消息的讲述
@Component
public class NiaoCaiBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor ,MergedBeanDefinitionPostProcessor ,DestructionAwareBeanPostProcessor{
public NiaoCaiBeanPostProcessor() {
System.out.println("NiaoCaiBeanPostProcessor ");
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor.postProcessBeforeInitialization " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor.postProcessAfterInitialization " + beanName);
return null;
}
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
// 返回非null,退出链式执行,只会调用beanProcessor.postProcessAfterInitialization方法
// 当 beanProcessor.postProcessAfterInitialization方法返回非null 会停止接下来的流程。构造调用,依赖注入,初始化等等都不会执行
System.out.println("InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation " + beanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// 返回false,退出链式执行,会停止依赖注入
System.out.println("InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation " + beanName);
return true;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean,String beanName) throws BeansException {
System.out.println("InstantiationAwareBeanPostProcessor.postProcessPropertyValues " + beanName+ " pvs : " + pvs.toString() + " pds : " + pds.toString());
return pvs;
}
@Override
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
System.out.println("MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition " + beanName);
}
@Override
public Class<?> predictBeanType(Class<?> beanClass, String beanName) throws BeansException {
//System.out.println("SmartInstantiationAwareBeanPostProcessor.predictBeanType " + beanName);
return null;
}
@Override
public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) throws BeansException {
System.out.println("SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors " + beanName);
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
System.out.println("SmartInstantiationAwareBeanPostProcessor.getEarlyBeanReference " + beanName);
return null;
}
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
System.out.println("DestructionAwareBeanPostProcessor.postProcessBeforeDestruction " + beanName);
}
@Override
public boolean requiresDestruction(Object bean) {
System.out.println("DestructionAwareBeanPostProcessor.requiresDestruction " + bean.toString());
return true;
}
}
@Comonent
public class ProcessorObject implements InitializingBean , DisposableBean, BeanNameAware{
// @Autowired
private Rely rely;
public ProcessorObject() {
System.out.println("ProcessorObject structure");
}
@PostConstruct
public void postConstruct(){
System.out.println("javax.annotation.postConstruct " + this.getClass().getName());
}
@PostConstruct
public void postConstructTwo(){
System.out.println("javax.annotation.postConstructTwo " + this.getClass().getName());
}
@PreDestroy
public void preDestroy(){
System.out.println("javax.annotation.preDestroy " + this.getClass().getName());
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy " + this.getClass().getName());
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean.afterPropertiesSet " + this.getClass().getName());
}
@Override
public void setBeanName(String name) {
System.out.println("BeanNameAware : " + name);
}
}
public class BeanPostProcessorTest extends SpringContext{
@Test
public void beanPostProcessorTest(){
this.application.refresh();
this.application.close();
}
}
实例化之前
InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation 执行标志着一个对象生命周期的开始
- InstantiationAwareBeanPostProcessor.postProcessBeforeInstantiation processorObject
- SmartInstantiationAwareBeanPostProcessor.determineCandidateConstructors processorObject
实例化与实例化之后
-
执行构造方法,实例化对象 ProcessorObject structure()
-
执行MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition MergedBeanDefinitionPostProcessor.postProcessMergedBeanDefinition processorObject
-
执行MergedBeanDefinitionPostProcessor.postProcessAfterInstantiation 标识对象实例化操作结束 InstantiationAwareBeanPostProcessor.postProcessAfterInstantiation processorObject
参数注入 6. InstantiationAwareBeanPostProcessor.postProcessPropertyValues processorObject pvs : PropertyValues: length=0 pds : 参数注入
- 基本Awate对象注入,详情请看关于Awate深入解读章节 BeanNameAware : processorObject
初始化
-
先执行@PostConstruct javax.annotation.postConstruct com.niaocaia.blog.spring.connet.beanLife.ProcessorObject javax.annotation.postConstructTwo com.niaocaia.blog.spring.connet.beanLife.ProcessorObject
-
在执行BeanPostProcessor.postProcessBeforeInitialization BeanPostProcessor.postProcessBeforeInitialization processorObject
-
然后执行InitializingBean的afterPropertiesSet InitializingBean.afterPropertiesSet com.niaocaia.blog.spring.connet.beanLife.ProcessorObject
-
在执行BeanPostProcessor.postProcessAfterInitialization BeanPostProcessor.postProcessAfterInitialization processorObject
-
最后执行DestructionAwareBeanPostProcessor.requiresDestruction , 执行之后,才能使用。 DestructionAwareBeanPostProcessor.requiresDestruction com.niaocaia.blog.spring.connet.beanLife.ProcessorObject@769e7ee8
销毁
先执行执行@preDestroy javax.annotation.preDestroy com.niaocaia.blog.spring.connet.beanLife.ProcessorObject
在执行DestructionAwareBeanPostProcessor 对象的postProcessBeforeDestruction DestructionAwareBeanPostProcessor.postProcessBeforeDestruction processorObject
最后执行 DisposableBean接口的destroy实现方法,整个baen生命周期结束 DisposableBean destroy com.niaocaia.blog.spring.connet.beanLife.ProcessorObject
总结
- @PostConstruct与@preDestroy的执行优先DisposableBean与InitializingBean
- @PostConstruct在BeanPostProcessor.postProcessBeforeInitialization之前执行,而InitializingBean在BeanPostProcessor.postProcessBeforeInitialization之后执行
- @preDestroy在DestructionAwareBeanPostProcessor.postProcessBeforeDestruction之前执行,而DisposableBean在DestructionAwareBeanPostProcessor.postProcessBeforeDestruction之后执行
- @PostConstruct与@preDestroy在一个类里面,可以标识在多个方法上。