前面創建和管理對象使用xml配置文件來完成,但是隨着對象的增多,xml配置文件也越來越大,為了防止這種現象的發生,注解的使用就應運而生。注解是在類或方法前面添加特定以"@+注解名"開頭的標識,實現xml配置文件的功能,如前面學習的創建對象、配置作用域、配置延遲加載等功能等。
組件掃描
容器會掃描指定的包及子包下面所有的類,如果該類前面有特定的注解,比如@Component,則容器會將其納入管理,不需要在xml中配置bean,其作用相當於在配置文件中配置一個bean元素,bean的id是帶注解@Component的類的第一個字母小寫后的名稱。
組件掃描的使用方法:
step1 在類面前添加特定的注解,比如@Component,默認的id是類名首字母小寫后的名稱
step2 在我們的配置文件當中,配置組件掃描
1 <context:component-scan base-package="package_name"/> <!--其中package_name代表我們要掃描的包-->
只有在組件類定義前面有如下注解標記時,才會掃描到Spring容器來管理,為后續使用其他注解提供必要條件。
@Component 通用注釋,spring框架的,Rod Johnson大神寫的
@Named 通用注釋,SUN公司的,模仿Spring的注釋,現在很少用,需要導額外的包
@Repository 持久化層組件注解,一般用於訪問數據庫
@Service 業務層組件注解,用於業務邏輯處理
@Controller 控制層組件注解
基本注解使用
后期做項目時,如果是控制層的類需加注解@Controller,如果是業務層的類需加@Service,如果是持久層的類需加@Repository,其他類使用@Component來添加。這里測試都是使用@Component來完成。
前期准備工作,是配置組件掃描,掃描我的測試包com.boe。
1 <!-- 配置組件掃描 --> 2 <context:component-scan base-package="com.boe"></context:component-scan>
(1)創建對象、作用域、延遲加載、生命周期使用注解
創建一個People類來使用注解。

1 package com.boe; 2 3 import javax.annotation.PostConstruct; 4 import javax.annotation.PreDestroy; 5 6 import org.springframework.context.annotation.Lazy; 7 import org.springframework.context.annotation.Scope; 8 import org.springframework.stereotype.Component; 9 10 @Component("p") 11 @Scope("singleton") 12 @Lazy(false) 13 public class People { 14 //默認構造方法 15 public People() { 16 System.out.println("創建一個人"); 17 } 18 19 //初始化方法和銷毀方法的注解,需導入tomcat 20 @PostConstruct 21 public void init() { 22 System.out.println("初始化了"); 23 } 24 @PreDestroy 25 public void destroy() { 26 System.out.println("銷毀了"); 27 } 28 }
junit測試

1 //測試@Component、作用域、延遲加載和生命周期 2 @Test 3 public void test1() { 4 String path="myIOC.xml"; 5 AbstractApplicationContext ac=new ClassPathXmlApplicationContext(path); 6 People people=ac.getBean("p",People.class); 7 System.out.println(people); 8 ac.close(); 9 }
測試結果
可以看出通過注解就可以創建對象,如圖是在作用域為singleton,延遲加載為false的情況下結果,其跟前面使用xml配置文件的效果是一樣的。需要注意的是配置銷毀方法只對singleton有效。
(2)使用@Autowired和@Qualifier依賴注入
這種方法適用於set方法和構造器方法注入,注解的位置可以寫在屬性前面,也可以寫在set或構造器方法前面,區別就是前者只能注入,后者是可以在set或構造器方法里添加其他的邏輯。默認情況下是byType類型注入,如果要指定名字需要配合@Qualifier("name")來使用。
案例通過將people注入到國家類和省類對象中來完成。
case1 set方法注入,將people注入到country
Country類

1 package com.boe; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.stereotype.Component; 6 7 @Component 8 public class Country { 9 //屬性 10 private People people; 11 //get set方法 12 public People getPeople() { 13 return people; 14 } 15 @Autowired 16 public void setPeople(@Qualifier("p")People people) { 17 this.people = people; 18 } 19 //構造方法 20 public Country() { 21 System.out.println("創建一個新的國家"); 22 } 23 //重寫toString方法 24 @Override 25 public String toString() { 26 return "Country [people=" + people + "]"; 27 } 28 }
junit測試

1 //測試使用@Autowired和@Qualifier注解-set方法注入 2 @Test 3 public void test2() { 4 String path="myIOC.xml"; 5 ApplicationContext ac=new ClassPathXmlApplicationContext(path); 6 Country c=ac.getBean("country",Country.class); 7 System.out.println(c); 8 }
測試結果
case2 構造器注入,將people注入到province
Province類

1 package com.boe; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.beans.factory.annotation.Qualifier; 5 import org.springframework.stereotype.Component; 6 7 @Component 8 public class Province { 9 //屬性 10 private People people; 11 //帶參數構造方法 12 @Autowired 13 public Province(@Qualifier("p")People people) { 14 System.out.println("新建一個省,有人民"); 15 this.people = people; 16 } 17 //默認構造方法 18 public Province() { 19 System.out.println("新建一個省,沒有人民"); 20 } 21 //重寫toString 22 @Override 23 public String toString() { 24 return "Province [people=" + people + "]"; 25 } 26 }
junit測試

1 //測試使用@Autowired和@Qualifier注解-構造方法注入 2 @Test 3 public void test3() { 4 String path="myIOC.xml"; 5 ApplicationContext ac=new ClassPathXmlApplicationContext(path); 6 Province province=ac.getBean("province",Province.class); 7 System.out.println(province); 8 }
測試結果
(3)使用@Resource依賴注入
這種注解只適合set方法注入,並且默認情況下是byName類型,如果@Resource(name="")里沒有添加名字或name找不到,則按照byType方式。
案例通過將people注入到縣類對象中來完成。
Village類

1 package com.boe; 2 3 import javax.annotation.Resource; 4 5 import org.springframework.stereotype.Component; 6 7 @Component 8 public class Village { 9 //屬性 10 private People people; 11 //set方法 12 @Resource(name="p") 13 public void setPeople(People people) { 14 this.people = people; 15 } 16 //構造方法 17 public Village() { 18 System.out.println("新建了一個村"); 19 } 20 //重寫 21 @Override 22 public String toString() { 23 return "Village [people=" + people + "]"; 24 } 25 }
junit測試

1 //測試使用@Resource-set方法注入 2 @Test 3 public void test4() { 4 String path="myIOC.xml"; 5 ApplicationContext ac=new ClassPathXmlApplicationContext(path); 6 Village v=ac.getBean("village",Village.class); 7 System.out.println(v); 8 }
測試結果
(3)使用@Value注入值
使用@Value注解,配合spring表達式的使用,可以將值注入到對象。
UserBean類

1 package com.boe; 2 3 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.stereotype.Component; 5 6 @Component("user") 7 public class UserBean { 8 @Value("clyang") //name賦值為clyang 9 //@Value("")也可以用在set方法前,區別就是屬性前使用只能賦值,如果set方法前寫除了賦值外還可以寫其他的功能 10 private String name; 11 //讀取properties屬性文件 12 @Value("#{config.pageSize}") //使用spring表達式 13 private String pageSize; 14 15 public String getName() { 16 return name; 17 } 18 public void setName(String name) { 19 this.name = name; 20 } 21 public String getPageSize() { 22 return pageSize; 23 } 24 public void setPageSize(String pageSize) { 25 this.pageSize = pageSize; 26 } 27 @Override 28 public String toString() { 29 return "UserBean [name=" + name + ", pageSize=" + pageSize + "]"; 30 } 31 }
xml配置文件中添加對properties文件的讀取
<!-- 讀取properties屬性文件 --> <util:properties id="config" location="classpath:config.properties"></util:properties>
junit測試

1 //測試用@Value注解,注入值(基本數據類型或者集合) 2 @Test 3 public void test5() { 4 //路徑配置文件 5 String path="myIOC.xml"; 6 //啟動spring容器,使用AbstractApplicationContext子接口 7 ApplicationContext ac=new ClassPathXmlApplicationContext(path); 8 //得到userBean 9 UserBean ub=ac.getBean("user", UserBean.class); 10 System.out.println(ub); 11 }
測試結果
結論
(1)使用注解可以減少xml配置文件中的內容,並且可以實現跟xml一樣的功能,原則是能使用注解的盡量使用注解,不能使用的就使用配置文件完成。
(2)@Resource默認采用byName類型注入,@Autowired默認采用byType,如果要改byName需配合@Qualifier一起使用
(3)@Resource來自JaveEE,需要有包annotation,@Autowired和@Qualifier來自Spring,參考下圖
參考博文