spring 第4天bean继承,init,destory-method

深入理解Spring容器中的bean
使用抽象bean
1.抽象bean被作为一种模板,在spring中被应用,在ApplicationContext初始化的时候,不会初始化抽象bean, 因此抽象bean的配置中可以没有 class.
2.抽象bean的作用主要是为了减少配置文件中多个bean之间拥有的重复的配置.
3.子bean无法从父bean中继承如下属性:depends-on,autowire,singleton,scope,lazy-init
4.如果 父bean写了class 则 子bean可以不用写class 和父类共用同一个实现类.
5.如果 父bean没有写class,则子bean必须写class
6.如果 父bean写了class,子bean也写了class,子bean覆盖 父bean的属性

<!-- 抽象bean -->
      <bean id="personTemplate" class="cn.sh.springmvc_java.Chinese" abstract="true">
      	<property name="axe" ref="stoneAxe_sf"/>
      </bean>
      <bean id="personTemplate1" abstract="true">
      		<property name="axe" ref="steelAxe_sf"/>
      </bean>
      
      <!--  子bean继承 -->
      <bean id="china_child" parent="personTemplate"/>
      
      <!-- 子bean 覆盖父类的bean -->
      <bean id="china_child1" parent="personTemplate">
      	<property name="axe" ref="steelAxe_sf"/>
      </bean>

spring的bean继承和java中继承完全不一样
1.spring中子bean和父bean可以是不同的类型,但java中继承可以保证子类是一种特殊的父类
2.spring中的bean的继承是实例之间的关系,因此主要表现为参数的延续;而java中的继承是类之间的关系,主要表现在方法和属性的延续
3.spring中子bean不可以作为父bean使用,不具备多态性,java中的子类实例完全可以当成父类实例使用


容器中的工厂bean:
1和前面介绍的静态工厂创建bean和实例工厂创建bean有区别,这里的工厂bean是spring中一种特殊的bean,该工厂bean必须实现FactoryBean接口,而且实现后的bean
只能作为工厂bean使用.
2.而且通过getBean()来获取工厂bean的时候返回的不是FactoyBean,而是工厂bean生产的java
实例
3.如果要获取 factoryBean 要在bean的id 前面加上  "&"

package cn.sh.springmvc_java.factory;

import org.springframework.beans.factory.FactoryBean;

import cn.sh.springmvc_java.American;
import cn.sh.springmvc_java.People;

/**
 * 采用 spring的工厂bean:默认 是singleton
 *
 */
public class PeopleFactory1 implements FactoryBean<People>{

	//People p=null;
	//这个方法只调用一次, 因为 scope="singleton" 如果prototype 就会每次调用
	@Override
	public People getObject() throws Exception {
	/*	// TODO Auto-generated method stub
		if(p==null){
			p=new American();
		}*/
		System.out.println("1");
		return new American();
	}

	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return American.class;
	}

	@Override
	public boolean isSingleton() {
		// TODO Auto-generated method stub
		return true;
	}
	
}


<!--可以去掉prototye 属性,这样 就是默认的单例了-->
<bean id="people" class="cn.sh.springmvc_java.factory.PeopleFactory1" scope="prototype"/> 


	/**
	 *测试 采用 factoryBean 创建的对象  发现获取不了配置ID
	 * xml创建的对象 可以获取配置时候的id 
	 */
	@Test
	public void test13(){ 
		ApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
		People p=act.getBean("people",People.class);
		System.out.println(p.sayHello("Mary"));
		System.out.println(p.sayGoodBye("Mary"));
		People p1=act.getBean("people",People.class);
		System.out.println(p==p1);  //单例就为true 否则为false

		//获取 factoryBean 本身
		System.out.println(act.getBean("&people"));
		System.out.println(p.getClass());
		p.toString();
		
		People pa=act.getBean("american",People.class);
		System.out.println(pa.sayHello("Mary"));
		System.out.println(pa.sayGoodBye("Mary"));
		pa.toString(); //会打印出 配置的id
	}


获取bean在配置文件中ID
实现BeanNameAware 的setBeanName(String name);


package cn.sh.springmvc_java;

import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
 * BeanNameAware 实现后,可以获取该bean的定义时的id
 * InitializingBean 实现后,可以在 spring初始化Bean完成后,执行指定的方法
 * DisposableBean :Bean在被销毁前,执行特点的方法
 * 
 * 注意: DisposableBean的 destory 方法 和 配置文件中的destory-method 只对scope的 singleton Bean有用
 *   可以将 Beans 的 default-init-method 和 default-destory-method和Bean的 方法 联合起来用 
 */
public class American implements People,BeanNameAware,InitializingBean,DisposableBean {

	private String beanName;
	
	@Override
	public void setBeanName(String name) {
		// TODO Auto-generated method stub
		System.out.println("执行BeanNameAware 的set方法 获取BeanName");
		this.beanName=name;
	}
	
	@Override
	public String sayHello(String name) {
		// TODO Auto-generated method stub
		return name+",hello";
	}

	@Override
	public String sayGoodBye(String name) {
		// TODO Auto-generated method stub
		return name+",Good Bye";
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		System.out.println("china实现类,部署该Bean是指定的ID为:"+beanName);
		return null;
	}

	//实现InitializingBean后,可以在初始化完成后 调用下面的方法   这样有代码污染
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("正在执行InitializingBean接口的afterPropertiesSet");
	}
	
	//在配置文件中配置  init-method  这种没有代码污染 推荐
	public void init(){
		System.out.println("init-method:正在初始化....");
	}

	@Override
	public void destroy() throws Exception {
		System.out.println("实现DisposableBean,即将被销毁...");
	}
	
	public void close(){
		System.out.println("destory-method:即将被销毁.....");
		
	}

	public String getBeanName() {
		return beanName;
	}
	
}

容器中bean的生命周期
1.spring可以管理singleton 作用域的bean的生命周期,spring可以精确的知道该bean何时被创建,何时初始化完成,容器何时销毁该bean.
2.对于prototype的bean.spring只负责创建,之后,完全交割客户端代码,容器不在跟踪其生命周期.

依赖关系注入之后的行为 spring提供了两种方式完成
1.使用init-mehtod
2.实现initializingBean 接口
3.如果这两个都写了, 会先执行 initialingBean 接口的方法 然后执行  init-method

Bean销毁之前的行为
1.使用 destory-method
2.实现despoableBean接口

    <bean id="peopleFactory" class="cn.sh.springmvc_java.factory.PeopleFactory"/>
      <bean id="china" factory-bean="peopleFactory" factory-method="getPeople">
      	<constructor-arg value="chin"/>
      </bean>
      <bean id="american" factory-bean="peopleFactory" factory-method="getPeople" scope="prototype" init-method="init" destroy-method="close">
      	<constructor-arg value="ame"/>
      </bean>

//测试init -method 和 destory -method
	@Test
	public void test15(){
		AbstractApplicationContext act=new ClassPathXmlApplicationContext("classpath*:applicationContent.xml");
		People pa=act.getBean("american",People.class);
		pa.toString();
		//未来让spring容器注册关闭钩子
		act.registerShutdownHook();
		System.out.println("aaa");
		pa=null;
		System.gc();
	}

你可能感兴趣的:(spring工厂bean,bean的继承)