注釋用法
@Required
用于setter方法上,它表明受影響的 bean 屬性在配置時必須放在 XML 配置檔案中,否則容器就會抛出一個BeanInitializationException 異常。public class Student{ private String name; private int age; @Required public void setAge(Integer age) { this.age = age; } public Integer getAge() { return age; } @Required public void setName(String name) { this.name = name; } public String getName() { return name; } }
//xml配置檔案裡沒有配置age這個屬性,會報BeanInitializationException的異常。 <context:annotation-config/> <bean id="student" class="Student"> <property name="name" value="lph"/> </bean>
@Autowired
預設按照類型方式進行bean比對
對屬性注釋,用來替代setter方法
對setter方法注釋
對構造函數注釋
public class Customer { @Autowired //對屬性注釋 private Person person; private int type; private String action; @Autowired //對setter方法注釋 public setPerson(Person person){ this.persion=persion; } @Autowired //對構造函數注釋 public Customer(Person person) { this.person = person; } }
使用掃描器來掃描包,省去在配置檔案裡配置相關bean//@Autowired注解是通過比對資料類型自動裝配Bean。 <bean id="CustomerBean" class="com.x'x'x'x.common.Customer"> <property name="action" value="buy" /> <property name="type" value="1" /> </bean> <bean id="PersonBean" class="com.x'x'x'x.common.Person"> <property name="name" value="xx" /> <property name="address" value="address ABC" /> <property name="age" value="29" /> </bean>
<context:component-scan base-package="xxx.xxxx.xxxxxx.xxxx"/>
依賴檢查
預設情況下,@Autowired将執行相關檢查,以確定屬性已經裝配正常。當Spring無法找到比對的Bean裝配,它會抛出異常。要解決這個問題,可以通過 @Autowired 的“required”屬性設定為false來禁用此檢查功能。
public class Customer { @Autowired(required=false)//即使沒有比對的bean,spring也不會報錯 private Person person; private int type; private String action; //getter and setter methods }
@Qualifier
建立多個具有相同類型的 bean 時,想要用一個屬性隻為它們其中的一個bean進行裝配,使用 @Qualifier 注釋和 @Autowired 注釋通過指定哪一個真正的 bean 将會被裝配來消除混亂。public interface Parent(){ public void iAmParent(){} }
@Component public class mother implements Parent{ public void iAmParent(){ ....... }
@Component public class father implements Parent{ public void iAmParent(){ ....... } }
此時我們可以用@Qualifier@Service public class SequenceServiceImpl implements SequenceService { //此處會報錯,因為parent有兩個實作類father和mother @Resource private Parent parent; }
@Service public class SequenceServiceImpl implements SequenceService { //使用@Qualifier指定bean @Qualifier(name="father") private Parent parent; }
@Resource
JSR-250規範定義的注解
和@Autowired作用類似,隻不過@Autowired是byType的方式自動注入,@Resource預設自動注入的方式為byName
@Resource裝配順序:
1. 如果同時指定了name和type,則從Spring上下文中找到唯一比對的bean進行裝配,找不到則抛出異常
2. 如果指定了name,則從上下文中查找名稱(id)比對的bean進行裝配,找不到則抛出異常
3. 如果指定了type,則從上下文中找到類型比對的唯一bean進行裝配,找不到或者找到多個,都會抛出異常
4. 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有比對,則回退為一個原始類型進行比對,如果比對則自動裝配;
@Bean @Configuration @Import 來代替xml配置檔案
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
<bean id="helloBean" class="com.xxx.hello.impl.HelloWorldImpl">
</beans>
**等效于以下JavaConfig的配置:**
@Configuration
public class AppConfig {
@Bean(name="helloBean")
public HelloWorld helloWorld() {
return new HelloWorldImpl();
}
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<import resource="config/customer.xml"/>
<import resource="config/scheduler.xml"/>
</beans>
**效于 @Import 功能**
@Configuration
@Import({ CustomerConfig.class, SchedulerConfig.class })
public class AppConfig {}
Spring自動掃描組建
啟用Spring元件掃描功能。使用@Component注釋來表示這是類是一個自動掃描元件。<context:component-scan base-package="xx.xxx.xxxx"/>
DAO層,添加@Component,表明這也是一個自動掃描元件。@Component public class CustomerDAO { @Override public String toString() { return "Hello , This is CustomerDAO"; } }
要建立元件的自定義名稱,你可以這樣自定義名稱:@Component public class CustomerService { @Autowired CustomerDAO customerDAO; @Override public String toString() { return "CustomerService [customerDAO=" + customerDAO + "]"; } }
自動掃描的組建類型(都是@Component的意思),對class注解@Service("AAA") public class CustomerService
@Repository – 表示在持久層DAO元件。 @Service – 表示在業務層服務元件。 @Controller – 表示在表示層控制器元件。 @Component – 訓示自動掃描元件。(不屬于以上三者的時候使用)
Spring過濾器元件自動掃描//include-filter 包含 <context:componnet-scan base-package="xx.xx.xxx"> <context:include-filter type="regex" expression="xx.xxx.*DAO.*"> </context> //exclude-filter 不包含
通過配置檔案來配置Spring
基于構造函數的依賴注入
注入class注入其他類型的值public class demo{ Test test; public void demo(Test test){ this.test=test; } } <bean id="demo" class="demo"> <constructor-args ref="test" /> <constructor-args ref="test2" /> </bean> //聲明2個class的bean <bean id="test" class="test" /> <bean id="test2" class="test2" />
通過索引注入public class demo{ public void demo(String str,int num){ ..... } } <bean id="demo" class="demo"> <constructor-args type="java.lang.String" value="axxxx" /> <constructor-args type="int" value="1" /> </bean>
<bean id="demo" class="demo"> <constructor-args index="0" value="axxxx" /> <constructor-args index="1" value="1" /> </bean>
基于設定函數的注入
public class demo{ public void test(String str){ ....... } } <bean id="demo" class="demo"> <property name="str" value="this is a String" /> </bean>
注入集合
public class demo{ List array; HashMap map; Porperties prop; }
//注入list <bean id="demo" class="demo"> <property name="array"> <list> <value>1</value> <value>2</value> <list> </property>
//注入map <property name="map"> <map> <entry key="1" value="a1"/> <entry key="2" value="a2"/> </map> </property>
//注入屬性 <property name="prop"> <props> <prop key="key1">xxx</prop> <prop key="key2">bbb</prop> </props> </property>
注入空值null
<bean><property name="asd"><null/></property></bean>
在Spring架構中,當一個類包含多個構造函數帶的參數相同,它總是會造成構造函數注入參數類型歧義的問題。
為了解決這個問題,應該為構造函數指定的确切資料類型,通過像這樣類型的屬性:
<bean id="CustomerBean" class="com.xxx.common.Customer"> <constructor-arg type="java.lang.String"> <value>xxx</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>188</value> </constructor-arg> <constructor-arg type="int"> <value>28</value> </constructor-arg> </bean> </beans>
自動裝配
1. 預設的模式
這是預設的模式,你需要通過 ‘ref’ 屬性來連接配接 bean。
<bean id="customer" class="com.yiibai.common.Customer"> <property name="person" ref="person" /> </bean> <bean id="person" class="com.yiibai.common.Person" />
2. 按屬性名稱自動裝配’
按屬性名稱自動裝配。在這種情況下,由于對“person” bean的名稱是相同于“customer” bean 的屬性(“person”)名稱,是以,Spring會自動通過setter方法将其裝配 – “setPerson(Person person)“.
<bean id="customer" class="com.yiibai.common.Customer" autowire="byName" /> <bean id="person" class="com.yiibai.common.Person" />
3. 按屬性的資料類型自動裝配
通過按屬性的資料類型自動裝配Bean。在這種情況下,由于“Person” bean中的資料類型是與“customer” bean的屬性>(Person對象)的資料類型一樣的,是以,Spring會自動通過setter方法将其自動裝配。– “setPerson(Person person)“.
<bean id="customer" class="com.yiibai.common.Customer" autowire="byType" /> <bean id="person" class="com.yiibai.common.Person" />
注入日期到bean屬性
以下寫法會報錯public class Customer { Date date; public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } }
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="customer" class="Customer"> <property name="date" value="2015-12-31" />//直接傳string類型的值給value </bean> </beans>
正确的方法
factory-bean
CustomDateEditor<bean id="customer" class="Customer"> <property name="date"> <bean factory-bean="dataFormat" factory-method="parse"> <constructor-arg value="2015-12-31" /> </bean> </property> </bean>
<bean id="dateEditor" class="org.springframework.beans.propertyeditors.CustomDateEditor"> <constructor-arg> <bean class="java.text.SimpleDateFormat"> <constructor-arg value="yyyy-MM-dd" /> </bean> </constructor-arg> <constructor-arg value="true" /> </bean> <bean class="org.springframework.beans.factory.config.CustomEditorConfigurer"> <property name="customEditors"> <map> <entry key="java.util.Date"> <ref local="dateEditor" /> </entry> </map> </property> </bean> <bean id="customer" class="Customer"> <property name="date" value="2015-12-31" /> </bean>
PropertyPlaceholderConfigurer
在聲明bean配置檔案和提供一個PropertyPlaceholderConfigurer映射到“database.properties”屬性檔案。<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>database.properties</value> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
Bean的切面處理
init-method 指定一個方法,在執行個體化 bean 時,調用該方法。
destroy-method 指定一個方法,從容器中移除 bean 之後,調用該方法。
singleton 和 prototype的差別( http://wiki.jikexueyuan.com/project/spring/bean-scopes.html)
<bean id="..." class="...." init-method="..." (destroy-method) scope="..." lazy-init="..." destroy-method="..." />
public example implements InitializingBean{ //實作InitializingBean接口,bean 初始化時可調用的初始化方法 public void do(){} } public example implements DisposableBean{ //實作DisposableBean接口,bean 銷毀時可調用的初始化方法 public void do(){} }
兩種後處理方法
Bean後處理器
Bean後處理器會在Bean執行個體建立成功之後,對Bean執行個體進行進一步的增強處理。
Bean後處理器必須實作BeanPostProcessor接口,同時必須實作該接口的兩個方法。
public example implements BeanPostProcessor{ //該方法的第一個參數是系統即将進行後處理的Bean執行個體,第二個參數是該Bean的配置id Object postProcessBeforeInitialization(Object bean, String name) throws BeansException: Object postProcessAfterinitialization(Object bean, String name) throws BeansException: }
容器後處理器
容器後處理器必須實作BeanFactoryPostProcessor接口,并實作該接口的一個方法
public example implements BeanFactoryPostProcessor{ postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory){} }
Bean可以繼承
<bean id="parent" class="....."> <property name="test" value="tttt" /> </bean> <bean id="child" class="....." parent="parent"> <property name="test1" value="tttt" /> </bean>