Spring中的Bean与java Bean
Java Bean的要求比较多,属于一个Java规范:每个成员变量都应该提供getter. setter方法。 Spring Bean几乎没有任何要求,唯一的要求是: 你在Spring配置文件中配置的XIL代码转换得到的java代码,- -定要 能成功执行。
抽象Bean
当你的配置文件有-批Bean配置的大量配置信息完全相同,只有少量配置不同。比如企业应用,大量的Service组件都需要注入DAO组件,此时大部分Servi ce组件所注入的DAO组件可能是相同的)大量配置参数, 可以将这批Bean中大量相同的配置信息抽取成Bean模板(抽象Bean)。各子Bean则可以只需继承该Bean模板,即可获得父Bean的大量配置参数 用子Bean的好处就是 1.简化配置。 2.提高Bean的可维护性
抽象Bean
abstract=" true'告诉Spring不要为该Bean创建实例
子Bean
指定parent属性的Bean就是子Bean. 子Bean和父Bean并没有逻辑上的继承关系,它只是从父Bean那里获取的一些配置信息 当子Bean的配置与父Bean的配置冲突时,子Bean的配置会覆盖父Bean的配置信息
<!--一批Bean有i相同的配置-->
<!--将一批Bean中相同的放到Bean模板中配置-->
<bean id="dog" class="com.example.ssm.day5.NewDog"/>
<bean id="dogTemplate" p:name="小花" p:age="12" abstract="true"/>
<bean id="dog1" class="com.example.ssm.day5.NewDog" parent="dogTemplate"/>
<bean id="dog2" class="com.example.ssm.day5.OldDog" parent="dogTemplate"/>
实例化Bean的三这种方法
spring容器中可以使用3种方法实例化一个Bean
-
调用该Bean的实现类的构造器
-
调用工厂的静态方法创建Bean factory-method:.告诉Spring要 调用的工厂方法。 classi指定工厂类的类名。 如果需要为工厂方法传入参数,使用constructor -arg来传入工厂方法参数
public class DogFactory {
private static Dog createDog(String type) {
if (type.equalsIgnoreCase("pet")) {
System.out.println("111111");
return (Dog) new NewDog();
}else {
return (Dog) new OldDog();
}
}
}
<bean id="dog" class="com.example.ssm.day5.DogFactory"
factory-method="createDog"
c:_0="pet"
p:name="小花"
/>
- 用实例工厂的实例工厂方法创建Bean factory-method;告诉Spring要调用的工厂方法。 Factory-bean:指定工厂Bean的id即可一- -这意味着你必须先配置工厂Bean的实例 如果需要为工厂方法传,入参数,使用constructor-arg来传入工厂方法参数
FactoryBean
接口是工厂Bean的标准接口,实现该接口的Bean通常作为工厂Bean使用, 当我们把工厂Bean部署在容器中、并通过getBean(方法来获取时,容器不会返回F actoryBean实例, 而是返回F actoryBean的产品(也就是该工厂Bean的get0bject方法的返回值) 。 如果需要获取工厂Bean本身,,并能不直接请求Bean id,而在Bean id前增加&符号。 假设想实现-个工具类: FactoryBean接口提供如下三个方法:
- 0bject get0bject(); 该方法返回工厂Bean所生产的产品
- Class getobjectType(): 该方法返回工厂Bean所生产的产品的类型。 该方法是弥补Java当年没有泛型的缺陷。
- boolean isSingleton();该方法返回工厂Bean所生产的产品是否为单例
Spring会检测Bean的实现类,-旦发现该实现类实现了FactoryBean接口,此时底层的源代码就变了。 factory = new GetFieldFactoryBean() ; factory . setXXxx(); //根据你配置的property元素来调用setter方法
优势
当你实现FactoryBean接口时: Sprins容器会, 自动帮你调用get0bject 9方法 而该方法完全是由你自己莱实现的,你在该方法中想干什么就千什么。
BeanNameAware
它也是接口注入 完全类似于ApplicationContextAware. ApplicationContextAmare作接口注入时,Spring容器是将 自身作为参数来注入Bean中。 BeanNaneAware作接口注入时,Spring容器是将该Bean的配置 id作为参数来注入Bean中。
需求
程序需要提前知道、并访问、调用Bean的配置id,此时就必须在Bean实现类中提前获取Bean的配置id。
public class TestBean implements ApplicationContextAware, BeanNameAware {
private ApplicationContext ctx;
private String beanName;
//该需要向spring容器发送事件。此时需要TestBean就需要获取spring容器
//接口注入
// Spring容器会自动检测容器中所有的Bean,如果发现某个Bean买现ApplicationContextAware接口
// Spring容器就会自动调用该Bean的setBeanName方法,
//调用该方法时,会将自己容器本身作为参数传入
@Override
public void setApplicationContext(ApplicationContext ctx) throws BeansException {
System.out.println("抵用setApplicationContext");
this.ctx = ctx;
}
public void send(String address, String content) {
System.out.println("当前Bean id 位" + this.beanName + "");
ctx.publishEvent(new EmailEvent(this, address, content));
}
//该需要向spring容器发送事件。此时需要TestBean就需要获取spring容器
//接口注入
// Spring容器会自动检测容器中所有的Bean,如果发现某个Bean买现ApplicationContextAware接口
// Spring容器就会自动调用该Bean的setBeanName方法,
//调用该方法时,会将自己容器本身作为参数传入
@Override
public void setBeanName(String beanName) {
System.out.println("接口注入setName");
this.beanName = beanName;
}
}
<!--
//该需要向spring容器发送事件。此时需要TestBean就需要获取spring容器
//接口注入
// Spring容器会自动检测容器中所有的Bean,如果发现某个Bean买现ApplicationContextAware接口
// Spring容器就会自动调用该Bean的setBeanName方法,
//调用该方法时,会将自己容器本身作为参数传入
-->
<bean id="testBean" class="com.example.ssm.day5.wp.TestBean"/>
结果