二(二)、基於註解形式配置bean
概述:
常用的註解有@Controller @Service @Repository @Component ;一般@Controller放在@Controller類上面即(表現層)標識表現層元件 ;@Service放在Service(業務層)的實現類上面,標識業務層元件 ;@Repository放在Repository(資料處理層)上面,標識持久層元件;@Component一般方式普通實體上面 基本元件,標識一個受到spring容器管理的元件;這幾個沒有明顯區分,其實可以混用但是為了程式碼的可讀性,一般都是按照前面的方式來處理;
基於註解方式配置bean,主要是通過 context:conponent-scan 來掃描 偵測 例項化 classpath下具有特定標識的元件;
一、配置bean:
步驟一、建立如下目錄結構
此外除了5個jar包外,需要新增spring-aop。否則可能報錯;
程式碼如下:
UserController:
1 package com.lixm.annotation.controller; 2 3 import org.springframework.stereotype.Controller; 4 5 @Controller 6 public class UserController { 7 8 public void execute() { 9 System.out.println("usercontroller execute...");View Code10 } 11 }
TestObject:
1 package com.lixm.annotation.entity; 2 3 import org.springframework.stereotype.Component; 4 5 @Component 6 public class TestObject { 7 8 }View Code
UserRepository:
1 package com.lixm.annotation.repository; 2 3 public interface UserRepository { 4 5 intView Codesave(); 6 7 }
UserRepositoryImpl:
1 package com.lixm.annotation.repository; 2 3 import org.springframework.stereotype.Repository; 4 5 @Repository(value = "userRepository") 6 public class UserRepositoryImpl implements UserRepository { 7 8 @Override 9 public int save() { 10 System.out.println("repository save..."); 11 return 0; 12 } 13 14 }View Code
UserService:
1 package com.lixm.annotation.service; 2 3 import org.springframework.stereotype.Service; 4 5 import com.lixm.annotation.repository.UserRepository; 6 7 @Service 8 public class UserService { 9 10 private UserRepository userRepository; 11 12 public int add() { 13 userRepository.save(); 14 System.out.println("userService add..."); 15 return 0; 16 } 17 18 }View Code
步驟二、測試配置的bean:
1 public class Main { 2 public static void main(String[] args) { 3 ApplicationContext context = new ClassPathXmlApplicationContext("bean-annotation.xml"); 4 TestObject testObject = (TestObject) context.getBean("testObject"); 5 UserController userController = (UserController) context.getBean("userController"); 6 UserService userService = (UserService) context.getBean("userService"); 7 UserRepository userRepository = (UserRepository) context.getBean("userRepository"); 8 System.out.println(testObject); 9 System.out.println(userController); 10 System.out.println(userService); 11 System.out.println(userRepository); 12 ((ConfigurableApplicationContext) context).close(); 13 } 14 15 }
bean-annotation.xml
需要額外引入context名稱空間
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 7 8 <!-- 指定spring ioc容器掃描的包 --> 9 <context:component-scan base-package="com.lixm.annotation"></context:component-scan> 10 11 </beans>
執行結果為:
com.lixm.annotation.entity.TestObject@166fa74d
com.lixm.annotation.controller.UserController@40f08448
com.lixm.annotation.service.UserService@276438c9
com.lixm.annotation.repository.UserRepositoryImpl@588df31b
說明配置bean成功;
二、context:component-scan屬性:
base-package :
指定需要掃描的基類包,spring容器會掃描這個基類包裡機器子包中所有的類,掃描到具有特定識別符號的類的上面會顯示S;
需要掃描多個包時,用逗號分割;
1 <context:component-scan base-package="com.lixm.annotation"></context:component-scan>
resource-pattern
屬性過濾特定的類1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 7 8 <!-- resource-pattern 屬性過濾特定的類 這裡只掃描 com.lixm.annotation.repository的包 --> 9 <context:component-scan base-package="com.lixm.annotation" resource-pattern="repository/*.class"></context:component-scan> 10 </beans>
這裡只掃描了repository包裡面的class,如果直接執行上面的main方法會報錯;原因是找不到對應的bean;
三、context:component-scan子節點:
exclude-filter 子節點指定排除哪些指定表示式的元件
這裡排除了,@Repository註解標識的類
1 <context:component-scan base-package="com.lixm.annotation" use-default-filters="false"> 2 <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 3 </context:component-scan>
context:include-filter子節點
指定包含哪些表示式的元件該子節點需要use-default-filters="false"配合使用1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xmlns:context="http://www.springframework.org/schema/context" 5 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd 6 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd"> 7 8 <context:component-scan base-package="com.lixm.annotation" use-default-filters="false"> 9 <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/> 10 </context:component-scan> 11 </beans>
子節點中常用type的說明:
type="annotation"基於註解的配置 type="assignable"指定class或者interface全名1 <context:component-scan base-package="com.lixm.annotation" use-default-filters="false"> 2 <context:include-filter type="assignable" expression="com.lixm.annotation.repository.UserRepository"/> 3 </context:component-scan>
只掃描com.lixm.annotation.repository.UserRepository類;
1 <context:component-scan base-package="com.lixm.annotation" > 2 <context:exclude-filter type="assignable" expression="com.lixm.annotation.repository.UserRepository"/> 3 </context:component-scan>
不掃描com.lixm.annotation.repository.UserRepository類
四、自動裝配:
spring 使用@Autowired來實現實現bean的自動裝配;
自動裝配的實現:
在需要呼叫的bean的類上面加上@Autowired,現在在Controller方法中呼叫Service的方法;實現程式碼如下:
修改UserController
1 package com.lixm.annotation.controller; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Controller; 5 6 import com.lixm.annotation.service.UserService; 7 8 @Controller 9 public class UserController { 10 11 12 @Autowired(required = true) 13 private UserService userService; 14 public void execute() { 15 userService.add(); 16 System.out.println("usercontroller execute..."); 17 } 18 }View Code
修改UserService
1 package com.lixm.annotation.service; 2 3 import org.springframework.beans.factory.annotation.Autowired; 4 import org.springframework.stereotype.Service; 5 6 import com.lixm.annotation.repository.UserRepository; 7 8 @Service 9 public class UserService { 10 11 @Autowired 12 private UserRepository userRepository; 13 14 public int add() { 15 userRepository.save(); 16 System.out.println("userService add..."); 17 return 0; 18 } 19 20 }View Code
測試自動裝配:
1 public static void main(String[] args) { 2 ApplicationContext context = new ClassPathXmlApplicationContext("bean-annotation.xml"); 3 TestObject testObject = (TestObject) context.getBean("testObject"); 4 UserController userController = (UserController) context.getBean("userController"); 5 UserService userService = (UserService) context.getBean("userService"); 6 UserRepository userRepository = (UserRepository) context.getBean("userRepository"); 7 System.out.println(testObject); 8 System.out.println(userController); 9 System.out.println(userService); 10 System.out.println(userRepository); 11 userController.execute(); 12 ((ConfigurableApplicationContext) context).close(); 13 14 }
執行結果:
com.lixm.annotation.entity.TestObject@701fc37a
com.lixm.annotation.controller.UserController@4148db48
com.lixm.annotation.service.UserService@282003e1
com.lixm.annotation.repository.UserRepositoryImpl@7fad8c79
repository save...
userService add...
usercontroller execute...
執行了bean元件中的方法,說明裝配成功;
關於@Autowired
1.使用位置:普通欄位(即使是非public)一切具有引數的方法都可以應用@Autowired註解;
2.屬性:value 和 require;
value是指定bean的名稱,如果只有一個value屬性,那麼value可以省略;@Autowired("xXXX")等同於@Autowired(“value="xXXX")
required 表示是否一定要裝配該bean;required=true,表示必須有,如果容器中沒有該bean,則報錯;required=false,表示可以沒有有,如果容器中沒有該bean,也不報錯。
required=true的集中情況:
- 如果查詢bean結果剛好為一個,就將該bean裝配給@Autowired指定的資料
- 如果查詢bean的結果不止一個,那麼@Autowired會根據名稱來查詢。
- 如果查詢bean的結果為空,那麼會丟擲異常。解決方法時,使用required=false
3.配合@Qualifier的使用;
當有多個介面實現類的bean時,可以使用@Qualifier("beanName") 指定裝配的bean
其他裝配方式:
spring 還支援@Resource(如果沒有bean名稱,那麼自動採用標註處的變數或方法名作為bean的名稱) 、 @Inject(沒有required屬性)註解推薦使用@Autowired
我從來不相信什麼懶洋洋的自由。我向往的自由是通過勤奮和努力實現的更廣闊的人生。 我要做一個自由又自律的人,靠勢必實現的決心認真地活著。