這篇文章記錄Spring IoC通過註解注入屬性的方法。
一、註解注入屬性一個簡單的案例
1)Spring配置文件引入context約束
<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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
2)Spring配置文件中開啓註解掃描
<context:component-scan base-package="com.pc.service"/>
注意,在第一步必須要引入context約束,否則無法出現context標籤。
3)在類上添加@Component註解
@Component("user")
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
4)編寫測試
ApplicationContext act = new ClassPathXmlApplicationContext("beans-ioc.xml");
User user = (User) act.getBean("user");
System.out.println(user);
二、Spring IoC常用註解詳解
1)Bean標註註解
- @Component :組件通用註解,常用於Model類
- @Controller :常用於對Controller實現類進行標註
- @Service:常用於對Service實現類進行標註
- @Repository:常用於對DAO實現類進行標註
@Component是Spring提供的通用的組件註解。@Component、@Controller、@Service和@Repository功能一樣,可以互換,我們使用不同註解主要爲了區分被註解的類處在不同的業務層,使邏輯更加清晰。這四個註解主要是定義bean,創建bean。
它們使用方法:
(1)標註在類上
(2)@Component("name")等於@Component(value="user")
(3)@Component相當於@Component("className")
2)Bean屬性注入註解
- @Value :注入普通類型屬性
- @Resource :注入對象類型
- @Autowired :注入對象類型,默認按照類型注入。結合@Qualifier註解完成按名稱的注入。
(1)@Value註解
例如,爲上面案例中User類中id和name一個初始值,我們可以在id和name屬性上面使用@Value註解,也可以在它們的set方法上使用@Value註解
@Component(value="user")
public class User {
@Value("1")
private Integer id;
@Value("lzgsea")
private String name;
public Integer getId() {
return id;
}
//@Value("1")
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
//@Value("lzgsea")
public void setName(String name) {
this.name = name;
}
}
(2)@Resource :注入對象類型
public class UserTest {
@Resource(name = "user")
private User user;
}
(3)@Autowired註解
public class UserTest {
// 按名注入,需要組件設置名稱
// @Resource(name = "user")
// 和上面功能一樣,按名注入
@Qualifier("user")
@Autowired
private User user;
}
3)Bean的作用範圍註解@Scope
Bean的範圍的註解:默認是單例的。
@Scope :在類上添加的,控制類生成的時候採用單例還是多例。
@Scope取值:
- singleton :單例
- prototype :多例
- request :request域,需要在web環境
- session :session域,需要在web環境
- application: context域,需要在web環境
- globalsession 集羣環境的session域,需要在web環境
4)Bean的生命週期註解
@PostConstruct :相當於init-method
@PreDestroy :相當於destroy-method
這兩註解用在方法上面。
@PostConstruct
public void init() {
System.out.println("初始化方法......");
}
@PreDestroy
public void destroy() {
System.out.println("銷燬方法......");
}
三、context:componet-scan
配置<context:annotation-config>後,會掃描@Required、@Autowired、@PostConstruct、@PreDestroy、@Resource等註解。
配置<context:component-scan base-package="xx">標籤後,spring可以自動去掃描base-pack下面或者子包下面的java文件,除了掃描<context:annotation-config>中所有的註解,還會掃描@Component、@Repository、@Service、@Controller、 @RestController、@ControllerAdvice、@Configuration 這些註解。
<context:component-scan>提供了兩個子標籤
- <context:include-filter>
- <context:exclude-filter>
在說明這兩個子標籤前,先說一下<context:component-scan>有一個use-default-filters屬性,該屬性默認爲true,這就意味着會掃描指定包下的全部的標有Spring註解的類,並註冊成bean。也就是@Component,@Controller,@Service,@Reposity等。所以如果僅僅是在配置文件中這麼寫
<context:component-scan base-package="lzgsea.*"/>
use-default-filter此時爲true那麼會對base-package包或者子包下的所有的進行java類進行掃描,並把匹配的java類註冊成bean。
可以發現這種掃描的粒度有點太大,如果你只想掃描指定包下面的Controller,該怎麼辦?此時子標籤<context:incluce-filter>就起到了勇武之地。如下所示
<context:component-scan base-package="lzgsea.*" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
這樣就會只掃描base-package包或者子包下所有@Controller下的java類,並註冊成bean。
use-dafault-filter在上面並沒有指定,默認就爲true,或者直接use-dafault-filter改爲true,那麼會對base-package包或者子包下的所有的進行java類進行掃描。
<context:component-scan base-package="lzgsea.*">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
此時,spring不僅掃描了@Controller,還掃描了指定包所在的子包service包下註解@Service的java類。此時指定的include-filter不任何起到作用。
另外在我參與的項目中可以發現在base-package指定的包中有的子包是不含有註解了,所以不用掃描,此時可以指定<context:exclude-filter>來進行過濾,說明此包不需要被掃描。
綜合以上說明:
use-default-filters="false"的情況下不會自動掃描,需要配置<context:include-filter>指定掃描哪些註解
use-dafault-filters="false"的情況下:<context:include-filter>指定的掃描。
use-default-filters="true"的情況下:<context:exclude-filter>指定的不掃描