文章目錄
- Bean的基礎配置
-
- 裝配機制
- 自動化裝配bean
- JAVA代碼裝配bean
- XML裝配bean
-
- 構造器初始化bean
- 裝配集合
- 屬性指派
Bean的基礎配置
裝配機制
Spring提供了三種裝配機制:
- 自動化裝配
- Java代碼裝配
- XML裝配
自動化裝配bean
Spring從兩個角度來實作自動化裝配:
- 元件掃描(component scanning):Spring會自動發現應用上下文中所建立的bean。
- 自動裝配(autowiring):Spring自動滿足bean之間的依賴。
Spring裝配bean首先需要知道裝配那些bean,即範圍和标志,是以需要元件掃描Spring上下文中需要建立bean的标志。
Spring通過@ComponentScan注解啟動掃描,@ComponentScan有一個屬性basePackages可以設定要掃描的基礎包,注意基礎包路徑為全路徑,當然可能你注意到了basePackages是一個複數,是以可以配置多個基礎包,若隻配置一個基礎包,可以省略basePackages;若不配置基礎包,那麼掃描的是配置類目前的包以及其子包。
@Configuration
@ComponentScan( "com.cxd.javaweb.service")
public class ComponentConfig {
}
或者
@Configuration
@ComponentScan(basePackages = "com.cxd.javaweb.service")
public class ComponentConfig {
}
或者
@Configuration
@ComponentScan(basePackages = {"com.cxd.javaweb.service","com.cxd.javaweb.bussiness"})
public class ComponentConfig {
}
@Configuration注解是表示這個類是配置類
若掃描的不是包,也可以掃描具體的類可以使用注解@ComponentScan的另外一個屬性basePackageClasses,用法與basePackages類似
現在使用注解@Configuration建立了配置類,使用@ComponentScan啟動自動掃描了,那麼建立bean的标志是什麼呢?
@Component注解就可以作為類建立bean的辨別,如:
@Component
public class HuaweiComputer implements IComputer {
public String getName(){
return "Huawei";
}
}
Spring應用上下文中所有bean都有一個ID,預設bean的ID是類名首字母小寫,如上類HuaweiComputer的ID為huaweiComputer,但是@Component可以設定bean的ID,使用屬性value,如:
//注解@Component的value屬性可以省略
@Component("LenovoPc")
public class LenovoComputer implements IComputer {
public String getName() {
return "Lenovo";
}
}
簡單的說,自動裝配就是融Spring自動滿足bean依賴的一種方法,在滿足依賴的過程中,會在Spring應用上下文中尋找比對某個bean,為了聲明要進行自動裝配我們需要借助一些注解,比如@Autowired,@Resource。
測試自動裝配
@Configuration
@ComponentScan(basePackages = {"com.cxd.javaweb.service"} )
public class ComponentConfig {
}
public interface IComputer {
public String getName();
}
@Component("LenovoPc")
public class LenovoComputer implements IComputer {
public String getName() {
return "Lenovo";
}
}
//@ContextConfiguration加載配置類,使用屬性classes
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = ComponentConfig.class)
public class ComputerTest {
@Autowired
@Qualifier("LenovoPc")
private IComputer iComputer;
@Test
public void testName(){
String name = iComputer.getName();
System.out.println(name);
}
}
結果:Lenovo
1、 @Component是基礎注解,還有 @Controller,@RestController,@Service,@Repository 這些注解為了程式的可讀性,以及不同層次使用的與@Component作用相同
@Controller和@RestController用于視圖層,常作用于接口
@Service用于業務層
@Repository用于資料通路層
注意:@RestController和@Controller的差別
@RestController是ResponseBody + Controller,使用@RestController傳回的是對象
@Controller可以與視圖解析器InternalResourceViewResolver配合使用傳回頁面
2、自動裝配bean的注解有:@Autowired,@Resource
注意:常比較的是@Autowired與@Resource
(1)@Autowired是Spring的注解,@Resource是JSR-250Java規範注解
(2)@Autowired按byType自動注入,而@Resource預設按 byName自動注入,@Autowired可以與@Qualifier配合使用實作通過name自動注入
(3)@Resource裝配順序
- 如果同時指定了name和type,則從Spring上下文中找到唯一比對的bean進行裝配,找不到則抛出異常
- 如果指定了name,則從上下文中查找名稱(id)比對的bean進行裝配,找不到則抛出異常
- 如果指定了type,則從上下文中找到類型比對的唯一bean進行裝配,找不到或者找到多個,都會抛出異常
- 如果既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;如果沒有比對,則回退為一個原始類型進行比對,如果比對則自動裝配;
建議使用@Resource
JAVA代碼裝配bean
盡管在很多場景下通過元件掃描和自動裝配實作Spring的自動化裝配是更為推薦的方式,但是有時候自動化配置的方案行不通,是以需要明确配置Spring。比如:你想要将第三方庫中的元件裝配到你的應用中,就不能使用@Component和@Autowired注解了。
首先需要建立配置類,聲明簡單的bean,如下:
@Configuration
public class SqlfxConfiguration {
@Bean(name = "sqlfxClient",initMethod="init")
public ClientMain sqlfx(){
return new ClientMain();
}
}
以上執行個體是公司添加sql分析需要配置的bean,其中ClientMain是第三方jar包
@Configuration注解辨別該類為配置類
@Bean注解告訴Spring這個方法将傳回一個對象,該對象要注冊為Spring應用上下文中的bean。bean的ID與帶有@Bean注解的方法名一樣,但是我們可以通過@Bean的一些屬性改變其預設值,比如通過name屬性改變bean的ID,如上面的例子,該bean的ID為“sqlxClient”,也可以使用屬性value。
@Bean注解中initMethod屬性表示初始化後要執行ClientMain類中的init()方法,還有一個屬性destroyMethod表示bean銷毀前要執行的方法
小知識:spring中若某個類中的某個方法需要在項目啟動的時候執行,那麼該類可以實作InitializingBean接口,重寫afterPropertiesSet()方法,通過這個方法調用要執行的那個方法。
當然建立bean的方式不一定都是使用new的方式,如下:
@Configuration
public class CacheConfiguration {
@Bean(name = "RcpEhCacheManager")
public CacheManager ehCacheManager() throws CacheException, IOException {
return CacheManager.newInstance(new ClassPathResource(
"/cache/caseEhcache.xml").getInputStream());
}
}
此執行個體是配置Ehcache緩存的方法,需要讀取xml檔案,使用newInstance建立CacheManager對象。
XML裝配bean
xml裝配bean的方式是Spring最早的裝配bean 的方案,但是随着自動裝配方式和Java代碼裝配方式的出現,xml裝配方式逐漸被人們棄用了,但是我們可以通過學習xml配置能很好的了解自動裝配和Java代碼裝配的原理,是以還是要了解的。
在使用JavaConfig的時候,需要建立一個帶有@Configuration注解的類,而在xml配置中需要建立一個xml檔案,并且要以**<beans>**元素為根,如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean class="com.cxd.javaweb.bean.DellComputer" id="dellComputer"></bean>
</beans>
bean的屬性:
id:唯一辨別,ioc容器中的Bean的key值,從ioc容器中擷取一個執行個體的時候,需要通過id來擷取
name:可以通過name從容器中擷取Bean,Bean的别名,有id的情況下,id為Bean的key,沒有id的情況下,name為執行個體的key
class:将哪一個類進行執行個體化,寫的是類的完全限定名(包名+類名)
使用反射對一個類進行執行個體化,如果寫錯了,在反射時會報ClassNotFoundException
lazy-init:延遲初始化,預設是在容器啟動的時候就進行加載,true是延遲加載,什麼時候從容器中擷取該Bean什麼時候才執行個體化,隻有在單例模式下生效
parent:指定該類的父類,将會繼承父類執行個體化後的所有屬性,執行個體化該類的時候,會先觸發父類的執行個體化,在該類進行執行個體化時,可以覆寫繼承父類中某個屬性的值,要求該類與父類是同一個類型(繼承),當然首先要将父類裝入容器中,parent寫的是父類Bean的id
abstract:不會在容器中建立該類的執行個體,如果從容器中擷取,會報錯
depend-on:依賴檢查,要執行個體化A類,但是執行個體化A類需要依賴B類,首先要保證B類已經執行個體化過了,B類的id。指定該Bean在執行個體化的時候依賴Bean,所依賴的Bean會将該Bean執行個體化之前進行執行個體化。depend-on寫的某個Bean的id
init-method:初始化方法,該Bean在執行個體化時會自動調用一個方法,該方法必須是無參的,直接寫方法名,不寫小括号,隻在單例模式下生效
destroy-method:容器關閉時調用的方法,該方法必須是無參的,且隻有單例模式下才能生效。調動ctx.close()就是關閉容器
構造器初始化bean
構造器初始化bean有兩種方案:
- <constructor-arg>元素
- 使用Spring3.0所引入的c-命名空間
Java代碼中構造函數如下:
public class Computer {
private DellComputer dellComputer;
public Computer(DellComputer dellComputer){
this.dellComputer = dellComputer;
}
public String getName(){
return dellComputer.getName();
}
}
xml配置如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean class="com.cxd.javaweb.bean.DellComputer" id="dellComputer">
</bean>
<bean class="com.cxd.javaweb.service.Computer" id="computer">
<constructor-arg ref="dellComputer"/>
</bean>
</beans>
測試類如下:
//@ContextConfiguration加載配置檔案,使用屬性locations
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath*:/spring-bean.xml")
public class XmlConfigTest {
@Resource
private DellComputer dellComputer;
@Test
public void testDell(){
String name = dellComputer.getName();
System.out.println(name);
}
}
或者
@RunWith(SpringJUnit4ClassRunner.class)
public class XmlConfigTest {
@Test
public void testDellName(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");
Computer dellComputer = (Computer)applicationContext.getBean("computer");
String name = dellComputer.getName();
System.out.println(name);
}
}
結果:dell
裝配集合
集合有list ,set其泛型可能是對象也可能是基本資料類型
若泛型為對象,如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean class="com.cxd.javaweb.service.Computer" id="computer">
<constructor-arg>
<list>
<ref bean="huaweiComputer">
<ref bean="levonoComputer">
<ref bean="dellComputer">
</list>
</constructor-arg>
</bean>
</beans>
若泛型為基本資料類型,如下:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean class="com.cxd.javaweb.service.Computer" id="computer">
<constructor-arg>
<list>
<value>品牌名:華為</value>
<value>品牌名:聯想</value>
<value>品牌名:戴爾</value>
</list>
</constructor-arg>
</bean>
</beans>
屬性指派
設定屬性用<property>元素為屬性的setter方法所提供的功能與<constructor-arg>元素為構造器所提供的功能是一樣的。如:
<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">
<bean class="com.cxd.javaweb.bean.DellComputer" id="dellComputer">
</bean>
<bean class="com.cxd.javaweb.service.Computer" id="computer">
<constructor-arg ref="dellComputer"/>
<property name="cname" value="電腦"/>
<property name="colour" value="黑色"/>
</bean>
</beans>