一、知识点
一个设计良好的组件不应该对容器有直接依赖。然而,让你的Bean感知容器资源有时候是必要的。
通过实现下面列举的某些感知接口,你的Bean可以感知Spring IoC容器中的资源。Spring通过这些接口中定义的setter方法将资源注入到你的Bean中。
BeanNameAware IoC容器中配置的Bean实例的名称
BeanFactoryAware 当前的Bean工厂,通过它你可以调用容器的服务
ApplicationContextAware* 当前的应用程序上下文,通过它你可以调用容器的服务
MessageSourceAware 消息资源,通过它你可以解析文本消息
ApplicationEventPublisherAware 应用程序事件发布者,通过它你可以发布应用程序事件
ResourceLoaderAware
资源加载器,通过它你可以加载外部资源
*实际上ApplicationContext接口扩展了MessageSource, ApplicationEventPublisher和ResourceLoader接口,所以你只需要知道应用程序上下文就可以访问所有这些服务。但是,最佳实践是选择一个能满足你需求并拥有最小作用域的感知接口。
感知接口中的setter方法在Bean属性设值之后、初始化回调方法调用之前调用,步骤如下:
(1)由构造函数或者工厂方法创建Bean实例。
(2)为Bean属性设值和Bean引用。
(3)调用感知接口中的setter方法。
(4)调用初始化回调方法。
(5)Bean就绪。
(6)容器关闭时,调用销毁回调方法。
注:一旦Bean实现感知接口,它们就与Spring绑定,无法在Spring IoC容器之外正常工作。
二、代码示例
Cashier类实现了BeanNameAware接口,让收银员Bean知道它在IoC容器中的Bean名称。注入Bean名称时,将其存储为收银员姓名。
/* * Copyright 2013-2015 */ package com.jackie.codeproject.springrecipesnote.springadvancedioc; import java.io.BufferedWriter; import java.io.FileWriter; import java.io.IOException; import java.util.Date; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import org.springframework.beans.factory.BeanNameAware; /** * Title: Cashier.java * 结账功能 * * @author jackie * @since Apr 24, 2013 9:14:49 PM * @version V1.0 */ public class Cashier implements BeanNameAware{ private String name; private BufferedWriter writer; /** * @param name the name to set */ public void setName(String name) { this.name = name; } @PostConstruct public void openFile() throws IOException { FileWriter fw = new FileWriter(name, true); writer = new BufferedWriter(fw); } public void checkout(ShoppingCart cart) throws IOException { double total = 0; for (Product product : cart.getItems()) { total += product.getPrice(); } writer.write(new Date() + "\t" + total + "\r\n"); writer.flush(); } @PreDestroy public void closeFile() throws IOException { writer.close(); } @Override public void setBeanName(String beanName) { this.name = beanName; } }Bean配置文件如下,删除掉了name属性的配置
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd"> <context:annotation-config /> <bean id="aaa" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.Battery"> <property name="name" value="AAA" /> <property name="price" value="2.5" /> </bean> <bean id="cdrw" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.Disc"> <property name="name" value="CD-RW" /> <property name="price" value="1.5" /> </bean> <bean id="dvdrw" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.Disc"> <property name="name" value="DVD-RW" /> <property name="price" value="3.0" /> </bean> <bean id="shoppingCart" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.ShoppingCart" /> <bean id="cashier1" class="com.jackie.codeproject.springrecipesnote.springadvancedioc.Cashier" /> </beans>注:可以直接指定字段名称和属性路径为FieldRetrievingFactoryBean和PropertyPathFactoryBean都实现了BeanNameAware接口。
<beans> Spring配置文件的根元素,包含一个或多个bean元素。
<bean> 用于告诉Spring容器一个类以及它是如何配置的。
class属性:Java Bean 类名(全路经)。
id属性:Java Bean在BeanFactory中的唯一标识,代码中通过BeanFactory获取JavaBean实例时需以此作为索引名称。
name属性:同上,如果给bean增加别名,可以通过name属性指定一个或多个id。
singleton属性:指定此Java Bean是否采用单例(Singleton)模式,如果设为“true”,则在BeanFactory作用范围内,只维护此Java Bean的一个实例,代码通过BeanFactory获得此Java Bean实例的引用。反之,如果设为“false”,则通过BeanFactory获取此Java Bean实例时,BeanFactory每次都将创建一个新的实例返回。
abstract属性:设定ApplicationContext是否对bean进行预先的初始化。
parent属性:定义一个模板。
autowire属性:bean自动装配模式。可选5种模式。
no:不使用自动装配。
Bean的引用必须通过ref元素定义。byName:通过属性名字进行自动装配。
byType:如果BeanFactory中正好有一个同属性类型一样的bean,就自动装配这个属性。如果有多于一个这样的bean,就抛出一个致命异常,它指出你可能不能对那个bean使用byType的自动装配。如果没有匹配的bean,则什么都不会发生,属性不会被设置。如果这是你不想要的情况(什么都不发生),通过设置dependency-check="objects"属性值来指定在这种情况下应该抛出错误。
constructor:这个同byType类似,不过是应用于构造函数的参数。如果在BeanFactory中不是恰好有一个bean与构造函数参数相同类型,则一个致命的错误会产生。
autodetect: 通过对bean 检查类的内部来选择constructor或byType。如果找到一个缺省的构造函数,那么就会应用byType。
dependency-check属性:依赖检查模式。可选四种。
none :不进行依赖检查。没有指定值的bean属性仅仅是没有设值。
Simple:对基本类型和集合(除了合作者外,比如其他的bean,所有东西)进行依赖检查。
Object:对合作者进行依赖检查。
all :对合作者,基本类型和集合都进行依赖检查。
lazy-init属性:延迟加载。True 或False 。
init-method属性:初始化方法,此方法将在BeanFactory创建JavaBean实例之后,在向应用层返回引用之前执行。一般用于一些资源的初始化工作。
destroy-method属性:销毁方法。此方法将在BeanFactory销毁的时候执行,一般用于资源释放。 factory-bean属性:通过实例工厂方法创建bean,class属性必须为空,factory-bean属性必
须指定一个bean的名字,这个bean一定要在当前的bean工厂或者父bean工厂中,并包含工厂方法。而工厂方法本身通过factory-method属性设置。
factory-method属性:设定工厂类的工厂方法。
depends-on属性:Bean依赖关系。一般情况下无需设定。Spring会根据情况组织各个依赖关系的构建工作。只有某些特殊情况下,如JavaBean中的某些静态变量需要进行初始化(这是一种BadSmell,应该在设计上应该避免)。通过depends-on指定其依赖关系可保证在此Bean加载之前,首先对depends-on所指定的资源进行加载。
<property> 用于设置一个属性。
name属性: 属性的名称。
<value> 指定bean的属性值。
<ref> 指定了属性对BeanFactory中其他Bean的引用关系。
bean=""属性:指定了属性对BeanFactory中其他Bean的引用关系。
local属性:local=""属性: 指定了属性对BeanFactory中其他Bean的引用关系。(仅在本地(同一个)xml文件里寻找bean。
parent属性:指定了属性对BeanFactory中其他Bean模板的引用关系。
<list> 指定bean的属性类型为List的属性值。
<map> 指定bean的属性类型为List的属性值。
<set> 指定bean的属性类型为List的属性值。
<props> 指定bean的属性类型为Properties的属性值。
<prop>
key属性:指定Properties的键
<idref> 用来设置属性值为容器中其他bean的id 或name。
<null> 指定一个空值。
&nb
Spring_Autowiring collaborators
在Spring3.2.2中自动装配类型,分别为:no(default)(不采用自动装配)、byName,byType,constructor下面来分别介绍一下这些是如何自动装配的
<bean id="foo" class="...Foo" autowire="autowire type">
Mode Explanation
no: (Default) No autowiring. Bean references must be defined via a ref element.
Changing the default setting is not recommended for larger deployments,
because specifying collaborators explicitly gives greater control and clarity.
To some extent, it documents the structure of a system.
byName:Autowiring by property name.
Spring looks for a bean with the same name as the property that needs to be autowired.
For example, if a bean definition is set to autowire by name,
and it contains a master property (that is, it has a setMaster(..) method),
Spring looks for a bean definition named master, and uses it to set the property.
byType:Allows a property to be autowired if exactly one bean of the property type exists in the container.
If more than one exists, a fatal exception is thrown,
which indicates that you may not use byType autowiring for that bean.
If there are no matching beans, nothing happens; the property is not set.
constructor:Analogous to byType, but applies to constructor arguments.
If there is not exactly one bean of the constructor argument type in the container, a fatal error is raised
案例分析:
1、创建CumputerBean类
package www.csdn.spring.autowire.bean; public class CumputerBean { // 电脑名称 private String name; public void setName(String name) { this.name = name; } }
2、创建DeptBean 类
package www.csdn.spring.autowire.bean; public class DeptBean { //部门名称 private String name; public void setName(String name) { this.name = name; } }
3、创建EmployeeBean