// Bean例子
public class HelloBean {
private static final Logger LOG = LoggerFactory
.getLogger(HelloBean.class);
private String name;
private Integer age;
protected String beanName;
public String getName() {
return name;
}
public void setName(String name) {
LOG.info("== 注入Bean屬性 [{}] ==", name);
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public HelloBean() {
LOG.info("== 構(gòu)造方法 [{}] ==", beanName);
}
public HelloBean(String name) {
this();
this.name = name;
}
}
1、XML配置Bean
<beans>
spring配置文件的根元素,包含一個(gè)或多個(gè)bean元素。
<bean>
屬性
default-dependency-check:默認(rèn)的依賴檢查模式。可選四種。
- none :不進(jìn)行依賴檢查。沒(méi)有指定值的bean屬性僅僅是沒(méi)有設(shè)值。
- simple:對(duì)基本類型和集合(除了合作者外,比如其他的bean,所有東西)進(jìn)行依賴檢查。
- object:對(duì)合作者進(jìn)行依賴檢查。
- all :對(duì)合作者,基本類型和集合都進(jìn)行依賴檢查。
default-lazy-init:默認(rèn)延遲加載。True 或False 。
class:Java Bean 類名。
id:Java Bean在BeanFactory中的唯一標(biāo)識(shí),代碼中通過(guò)BeanFactory獲取JavaBean實(shí)例時(shí)需以此作為索引名稱。
name:同上,如果給bean增加別名,可以通過(guò)name屬性指定一個(gè)或多個(gè)id。
singleton:指定此Java Bean是否采用單例(Singleton)模式,如果設(shè)為“true”,則在BeanFactory作用范圍內(nèi),只維護(hù)此Java Bean的一個(gè)實(shí)例,代碼通過(guò)BeanFactory獲得此Java Bean實(shí)例的引用。反之,如果設(shè)為“false”,則通過(guò)BeanFactory獲取此Java Bean實(shí)例時(shí),BeanFactory每次都將創(chuàng)建一個(gè)新的實(shí)例返回。
abstract:設(shè)定ApplicationContext是否對(duì)bean進(jìn)行預(yù)先的初始化。
parent:定義一個(gè)模板。
autowire:bean自動(dòng)裝配模式??蛇x5種模式。
- no:不使用自動(dòng)裝配。Bean的引用必須通過(guò)ref元素定義。
- byName:通過(guò)屬性名字進(jìn)行自動(dòng)裝配。
- byType:如果BeanFactory中正好有一個(gè)同屬性類型一樣的bean,就自動(dòng)裝配這個(gè)屬性。如果有多于一個(gè)這樣的bean,就拋出一個(gè)致命異常,它指出你可能不能對(duì)那個(gè)bean使用byType的自動(dòng)裝配。如果沒(méi)有匹配的bean,則什么都不會(huì)發(fā)生,屬性不會(huì)被設(shè)置。如果這是你不想要的情況(什么都不發(fā)生),通過(guò)設(shè)置dependency-check="objects"屬性值來(lái)指定在這種情況下應(yīng)該拋出錯(cuò)誤。
- constructor:這個(gè)同byType類似,不過(guò)是應(yīng)用于構(gòu)造函數(shù)的參數(shù)。如果在BeanFactory中不是恰好有一個(gè)bean與構(gòu)造函數(shù)參數(shù)相同類型,則一個(gè)致命的錯(cuò)誤會(huì)產(chǎn)生。
- autodetect: 通過(guò)對(duì)bean 檢查類的內(nèi)部來(lái)選擇constructor或byType。如果找到一個(gè)缺省的構(gòu)造函數(shù),那么就會(huì)應(yīng)用byType。
init-method:初始化方法,此方法將在BeanFactory創(chuàng)建JavaBean實(shí)例之后,在向應(yīng)用層返回引用之前執(zhí)行。一般用于一些資源的初始化工作。
destroy-method:銷毀方法。此方法將在BeanFactory銷毀的時(shí)候執(zhí)行,一般用于資源釋放。
factory-bean:通過(guò)實(shí)例工廠方法創(chuàng)建bean,class屬性必須為空,factory-bean屬性必
須指定一個(gè)bean的名字,這個(gè)bean一定要在當(dāng)前的bean工廠或者父bean工廠中,并包含工廠方法。而工廠方法本身通過(guò)factory-method屬性設(shè)置。
factory-method:設(shè)定工廠類的工廠方法。
depends-on:Bean依賴關(guān)系。一般情況下無(wú)需設(shè)定。Spring會(huì)根據(jù)情況組織各個(gè)依賴關(guān)系的構(gòu)建工作。只有某些特殊情況下,如JavaBean中的某些靜態(tài)變量需要進(jìn)行初始化(這是一種BadSmell,應(yīng)該在設(shè)計(jì)上應(yīng)該避免)。通過(guò)depends-on指定其依賴關(guān)系可保證在此Bean加載之前,首先對(duì)depends-on所指定的資源進(jìn)行加載。
子標(biāo)簽
**<property> **
用于設(shè)置一個(gè)屬性。
name屬性:屬性的名稱。
value屬性: 指定bean的屬性值。BeanFactory將自動(dòng)根據(jù)Java Bean對(duì)應(yīng)的屬性類型加以匹配。如果需要將屬性值設(shè)定為null,必須使用<null/>節(jié)點(diǎn)。
ref屬性: 指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。
**<value> **
指定bean的屬性值。
**<ref> **
指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。
bean屬性:指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。
local屬性:指定了屬性對(duì)BeanFactory中其他Bean的引用關(guān)系。(僅在本地(同一個(gè))xml文件里尋找bean。
parent屬性:指定了屬性對(duì)BeanFactory中其他Bean模板的引用關(guān)系。
**<list> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。
**<map> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。
**<set> **
指定bean的屬性類型為L(zhǎng)ist的屬性值。
**<props> **
指定bean的屬性類型為Properties的屬性值。
**<prop> **
key屬性:指定Properties的鍵
**<idref> **
用來(lái)設(shè)置屬性值為容器中其他bean的id 或name。
**<null> **
指定一個(gè)空值。
**<constructor-arg> **
使用構(gòu)造方法注入,指定構(gòu)造方法的參數(shù)。
index屬性:設(shè)置參數(shù)的序號(hào)。
ref屬性:同ref
type屬性:參數(shù)類型。
value屬性:參數(shù)的值。
**<lookup-method> **
lookup方法注入
bean屬性:要注入的bean名
name屬性:要注入的方法名稱
**<replaced-method> **
用來(lái)把已存在的方法實(shí)現(xiàn)替換為其他的實(shí)現(xiàn)。
name屬性:要替換的方法名
replacer屬性:替換者類, 實(shí)現(xiàn)org.springframework.beans.factory.support.MethodReplacer
接口)
**<arg-type> **
方法返回的類型
util命名空間配置
- 集合:
<util:list> </util:list>
<util:map> </util:map>
<util:set> </util:set>
<util:list id="placeHolderList">
<value>test</value>
</util:list>
- properties屬性文件
util:properties:可以通過(guò)location屬性指定其properties屬性文件的位置
<util:properties> </util:properties>
<util:properties id="settings" location="classpath:config/placeholder.properties"/>
例子:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd"
default-lazy-init="true">
<bean name="helloBean" class="com.stepbystep.spring4.samples.beans.HelloBean"
init-method="initMethod" destroy-method="destroyMethod">
<property name="name" value="Spring"></property>
<property name="age" value="0"></property>
</bean>
<bean name="helloBean2" class="com.stepbystep.spring4.samples.beans.HelloBean"
p:name="test" p:age="2"/>
<bean name="helloBean3" class="com.stepbystep.spring4.samples.beans.HelloBean" p:age="3"/>
<bean name="helloBean4" class="com.stepbystep.spring4.samples.beans.HelloBean" p:name="${name}" p:age="4"/>
<!--<bean class="com.stepbystep.spring4.samples.beans.lifecycle.BeanFactoryPostProcessorAdapter"></bean>-->
<!--<bean class="com.stepbystep.spring4.samples.beans.lifecycle.BeanPostProcessorAdapter"></bean>-->
<util:list id="list">
<value>java</value>
<value>bean</value>
</util:list>
<util:map id="map" map-class="java.util.HashMap" >
<entry key="key1" value-ref="some1"/>
<entry key="key2" value-ref="some2"/>
<entry key="key3" value-ref="some3"/>
</util:map>
<bean id="someBean" class="cn.itcast.spring._util.SomeBean">
<property name="someStrArray" ref="strArray"/>
<property name="someObjArray" ref="objArray"/>
<property name="someList" ref="list"/>
<property name="someMap" ref="map"/>
</bean>
</beans>
2、Groovy配置Bean
例子:
import com.stepbystep.spring4.samples.beans.HelloBean
beans{
helloBean(HelloBean){
name='GroovyBean'
age=8
}
}
3、Bean的實(shí)例化方法
步驟:
(1)實(shí)例化一個(gè)BeanFactory(可以根據(jù)具體需要從BeanFactory的多個(gè)實(shí)現(xiàn)類中實(shí)例化一個(gè));
BeanFactory beanFactory0 = new DefaultListableBeanFactory();
BeanFactory beanFactory1 = new ClassPathXmlApplicationContext();
BeanFactory beanFactory2 = new FileSystemXmlApplicationContext();
BeanFactory beanFactory3 = new GenericApplicationContext();
BeanFactory beanFactory4 = new GenericGroovyApplicationContext();
BeanFactory beanFactory5 = new GenericXmlApplicationContext();
BeanFactory beanFactory6 = new StaticApplicationContext();
BeanFactory beanFactory7 = new StaticListableBeanFactory();
BeanFactory beanFactory8 = new AnnotationConfigApplicationContext();
(2)實(shí)例化一個(gè)BeanDefinitionReader:
有兩個(gè)實(shí)現(xiàn)類:XmlBeanDefinitionReader(讀取xml中的bean)GroovyBeanDefinitionReader(讀取groovy中的bean);實(shí)例化時(shí)將BeanFactory作為參數(shù)傳入:
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
GroovyBeanDefinitionReader beanDefinitionReader = new GroovyBeanDefinitionReader(beanFactory);
(3)實(shí)例化Resource:
同樣有多個(gè)實(shí)現(xiàn)類,用于不同的資源文件:
Resource resource0 = new ClassPathResource();
Resource resource1 = new ByteArrayResource();
Resource resource2 = new DescriptiveResource();
Resource resource3 = new FileSystemResource();
Resource resource4 = new InputStreamResource();
Resource resource5 = new PathResource();
Resource resource6 = new UrlResource();
Resource resource7 = new VfsResource();
(4)load資源文件:
beanDefinitionReader.loadBeanDefinitions(resource);
(5)最后就是通過(guò)BeanFactory對(duì)bean配置文件中的bean進(jìn)行各種花式操作了,包括獲取一個(gè)bean實(shí)例、讀取properties屬性文件等。
例子:
從xml文件讀取bean:
@Test
public void testBeanFactoryXml(){
BeanFactory beanFactory = new DefaultListableBeanFactory();
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader((BeanDefinitionRegistry) beanFactory);
ClassPathResource resource = new ClassPathResource("spring/hello-bean.xml");
beanDefinitionReader.loadBeanDefinitions(resource);
HelloBean bean = beanFactory.getBean("helloBean",HelloBean.class);
bean.sayHello();
printBeans((ListableBeanFactory) beanFactory);
}
private void printBeans(ListableBeanFactory beanFactory) {
StringBuilder sb =new StringBuilder("\n");
for (String s : beanFactory.getBeanDefinitionNames()) {
sb.append(s).append("\n");
}
LOG.info("beanNames = {}",sb.toString());
LOG.info("beanNames.size = {}",beanFactory.getBeanDefinitionCount());
}
從Groovy文件讀bean:
@Test
public void testBeanFactoryGroovy(){
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
GroovyBeanDefinitionReader beanDefinitionReader = new GroovyBeanDefinitionReader(beanFactory);
ClassPathResource resource = new ClassPathResource("spring/helloBean.groovy");
beanDefinitionReader.loadBeanDefinitions(resource);
HelloBean bean = beanFactory.getBean(HelloBean.class);
org.junit.Assert.assertNotNull(bean);
bean.sayHello();
LOG.info("beanFactory = {}",beanFactory );
}
4、Bean的生命周期
Spring Bean的完整生命周期從創(chuàng)建Spring容器開(kāi)始,直到最終Spring容器銷毀Bean,這其中包含了一系列關(guān)鍵點(diǎn):

監(jiān)視Bean的生命周期
為BeanFactory添加BeanPostProcessor
-
自定義BeanPostProcessor,實(shí)現(xiàn)相應(yīng)的接口和接口方法:
public class BeanPostProcessorAdapter implements BeanPostProcessor, InstantiationAwareBeanPostProcessor,DestructionAwareBeanPostProcessor { ... }BeanPostProcessor:
初始化前處理:Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
初始化后處理:Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
InstantiationAwareBeanPostProcessor:
實(shí)例化前處理:Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException;
實(shí)例化后處理:boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException;
實(shí)例化處理屬性:PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException;
DestructionAwareBeanPostProcessor:
銷毀 前處理: void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException;
boolean requiresDestruction(Object bean);
Bean實(shí)現(xiàn)對(duì)應(yīng)的接口可以在其生命周期的特定時(shí)間回調(diào)相應(yīng)的接口方法:
InitializingBean
void afterPropertiesSet() throws Exception; // 初始化 接口回調(diào)DisposableBean
void destroy() throws Exception; // 銷毀 接口回調(diào)BeanNameAware
void setBeanName(String name); // 執(zhí)行Aware操作,讓Bean獲取自己在BeanFactory配置中的名字(根據(jù)情況是id或者name)