1. 程式人生 > >Spring入門學習(基於註解的方式配置Bean) 第十二節

Spring入門學習(基於註解的方式配置Bean) 第十二節

Spring入門學習(基於註解的方式配置Bean)

指定SpringIOC容器掃描包

在這裡插入圖片描述

分別建立repository,service,controller

  1. 新增類TestObject,使用@Component註解標註為元件:
    @Component
    public class TestObject {
    	
    }
    
  2. 建立repository層相關類:
    public interface UserRepository
    { void save(); }
    UserRepositoryImpl實現UserRepository介面,並在類上添加註解@Repository
    @Repository
    public class UserRepositoryImpl implements UserRepository {
    
    	@Autowired(required=false)
    	private TestObject testObject;
    	
    	@Override
    	public void save() {
    		System.out.println("UserRepositoryImpl Save...");
    		System.
    out.println(testObject); } }
  3. 建立service層相關類,並在類上新增@Service註解:
    @Service
    public class UserService {
    
    	private UserRepository userRepository;
    	
    	@Autowired
    	public void setUserRepository(UserRepository userRepository) {
    		this.userRepository = userRepository;
    	}
    
    	public void add(){
    		System.out.println
    ("UserService add..."); userRepository.save(); } }
  4. 建立controller層,添加註解@Controller:
    @Controller
    public class UserController {
    	
    	@Autowired
    	private UserService userService;
    
    	public void execute() {
    		System.out.println("UserController execute...");
    		userService.add();
    	}
    }
    
  5. 建立
    <!-- 指定SpringIOC容器掃描的包 -->
    <!-- 可以通過resource-pattern指定掃描的資源 -->
    <context:component-scan 
    	base-package="com.fafa.spring.bean.annotation"></context:component-scan>
    
  6. 新建測試類:
    public class Main {
    
    	public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml");
    		
    		TestObject to = (TestObject)ctx.getBean("testObject");
    		System.out.println(to);
    		
    		UserController userController = (UserController) ctx.getBean("userController");
    		System.out.println(userController);
    		// userController.execute();
    		
    		UserService userService = (UserService) ctx.getBean("userService");
    		System.out.println(userService);
    		
    		UserRepository userRepository = (UserRepository) ctx.getBean("userRepositoryImpl");
    		System.out.println(userRepository);
    	}
    }
    
    測試結果:
    [email protected]
    [email protected]
    [email protected]
    [email protected]8647f
    
  7. 如果此時使用resource-pattern指定掃描的類,則容器中就只會有指定的掃描的bean
    <context:component-scan 
    	base-package="com.fafa.spring.bean.annotation"
    	resource-pattern="repository/*.class"></context:component-scan>
    
  8. 如果要注入的bean可能不存在的時候可以使用@Autowired(required=false)指定不是必須的
    註釋掉TestObject類中的@Component,將UserRepositoryImplTestObject的註解設定為@Autowired(required=false)測試:
    	public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml");
    		
    		UserRepository userRepository = (UserRepository) ctx.getBean("userRepositoryImpl");
    		userRepository.save();
    		System.out.println(userRepository);
    	}
    
    測試結果:testObject為null
    UserRepositoryImpl Save...
    null
    [email protected]f2a691
    
    該方式避免了在使用的bean時候發生bean找不到的錯誤。
  9. 再新建一個UserJdbcRepositoryImpl.java實現UserRepository介面,新增@Repository註解:
    @Repository
    public class UserJdbcRepositoryImpl implements UserRepository {
    	@Override
    	public void save() {
    		System.out.println("UserJdbcRepository save。。。。。");
    	}
    
    }
    
  10. 此時在通過UserRepository介面呼叫方法的時候,會報bean不唯一的錯:
    public class Main {
    
    	public static void main(String[] args) {
    		ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath*:beans-annotation.xml");
    		 
    		UserController userController = (UserController) ctx.getBean("userController");
    		System.out.println(userController);
    		userController.execute();
    	}
    }
    
    錯誤資訊:
    No qualifying bean of type [com.fafa.spring.bean.annotation.repository.UserRepository] is defined: expected single matching bean but found 2: userJdbcRepositoryImpl,userRepositoryImpl
    
    要解決這個問題,可以使用@Qualifier註解指定呼叫介面對應的bean名稱,如UserSerive中:
    @Service
    public class UserService {
    
    	private UserRepository userRepository;
    	
    	@Autowired
    	public void setUserRepository(@Qualifier("userJdbcRepositoryImpl") UserRepository userRepository) {
    		this.userRepository = userRepository;
    	}
    
    	public void add(){
    		System.out.println("UserService add...");
    		userRepository.save();
    	}
    }
    
    使用@Qualifier("userJdbcRepositoryImpl")標註使用UserJdbcRepositoryImpl類中的方法:
    [email protected]
    UserController execute...
    UserService add...
    UserJdbcRepository save。。。。。
    
  11. 此外還可以使用context:exclude-filtercontext:include-filter來指定在包掃描時要包含的包或要排除的包,以及使用use-default-filters="false"來指定只掃描指定的元件
    <?xml version="1.0" encoding="UTF-8"?>
    <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-4.1.xsd">
    	
    	<!-- 指定SpringIOC容器掃描的包 -->
    	<!-- 可以通過resource-pattern指定掃描的資源 -->
    	<!-- <context:component-scan 
    		base-package="com.fafa.spring.bean.annotation"
    		resource-pattern="repository/*.class"></context:component-scan> -->
    		
    	<!-- context:exclude-filter 子節點指定排除哪些指定表示式的元件 -->
    	<!-- 
    		context:include-filter 子節點指定包含哪些指定表示式的元件,該子節點需要use-default-filters 配合使用
    		use-default-filters: 預設的filter是會全部掃描元件的,設為false後就只會使用指定的元件
    	 -->
    	<context:component-scan 
    		base-package="com.fafa.spring.bean.annotation">
    		<!-- use-default-filters="false" -->
    		
    		<!-- <context:exclude-filter type="annotation" 
    			expression="org.springframework.stereotype.Repository"/> 
    		
    		
    		<context:include-filter type="annotation" 
    			expression="org.springframework.stereotype.Repository"/> -->
    		
    		
    		<context:exclude-filter type="assignable" 
    			expression="com.fafa.spring.bean.annotation.repository.UserJdbcRepositoryImpl"/>
    		
    		
    		<!-- <context:include-filter type="assignable" 
    			expression="com.fafa.spring.bean.annotation.repository.UserRepositoryImpl"/>  -->
    		
    	</context:component-scan>
    		
    </beans>