Spring學習記錄(十一)---使用注解和自動裝配


Spring支持用注解配置Bean,更簡便。

 上面的組件,是根據實際情況配的。比如寫的一個類,是做業務處理的,那就用注解@Service表示服務層組件,以此類推。將整體分成不同部分。

 

要在xml加入context命名空間

1      <!-- 指定Spring IOC容器掃描的包 -->
2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"></context:component-scan>

 這樣,就表示要自動掃描 基類包的類以及子包中的類。類中有注解,就會被管理

 

 例子:

 目錄結構如下,第一個annotation包為要掃描的包,有下面三個子包:controller、repository、service

類里面都是一個簡單的注解和一個方法:

1    //TestObject.java
2 package com.guigu.spring.beans.annotation;
3 
4 import org.springframework.stereotype.Component;
5 
6 @Component
7 public class TestObject {
8     
9 }

 

 

 1    //UserController.java
 2 package com.guigu.spring.beans.annotation.controller;
 3 import org.springframework.stereotype.Controller;
 4 
 5 @Controller
 6 public class UserController {
 7 
 8     public void execute(){
 9         System.out.println("UserController execute...");
10     }
11 }

 

 

 1      //UserRepository.java
 2 package com.guigu.spring.beans.annotation.repository;
 3 public interface UserRepository {
 4     
 5     void save();
 6 }
 7 
 8     //UserRepositoryImpl.java  繼承 UserRepository
 9 package com.guigu.spring.beans.annotation.repository;
10 import org.springframework.stereotype.Repository;
11 
12 @Repository("userRepository");
13 public class UserRepositoryImpl implements UserRepository {
14 
15     @Override
16     public void save() {
17         System.out.println("UserRepositoryImpl Save...");
18     }
19 
20 }

 寫一個繼承,為了說明注解命名可以更改,這里改成了userRepository,否則是默認的userRepositoryImpl,下面講。

 

 1      //UserService.java
 2 package com.guigu.spring.beans.annotation.service;
 3 
 4 import org.springframework.stereotype.Service;
 5 
 6 @Service
 7 public class UserService {
 8     
 9     public void add(){
10         System.out.println("UserService add...");
11     }
12 }

 

 xml最上面已經配置,最后main函數:

 1 package com.guigu.spring.beans.annotation;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.support.ClassPathXmlApplicationContext;
 5 
 6 import com.guigu.spring.beans.annotation.controller.UserController;
 7 import com.guigu.spring.beans.annotation.repository.UserRepository;
 8 import com.guigu.spring.beans.annotation.service.UserService;
 9 
10 public class Main {
11 
12     public static void main(String[] args) {
13         
14         ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");
15         TestObject to = (TestObject) ctx.getBean("testObject");
16         System.out.println(to);
17         UserController userController=(UserController) ctx.getBean("userController");
18         System.out.println(userController);
19         UserService userservice=(UserService) ctx.getBean("userservice");
20         System.out.println(userservice);
21         UserRepository userRepository=(UserRepository) ctx.getBean("userRepository");  
22         System.out.println(userRepository);
23     }
24 
25 }

 

 輸出如下:說明對象被創建了

xml里面沒有bean,那main函數怎么獲取Bean呢?

就是用最上面圖中藍色字體。Spring默認命名,名字是它的類名第一個字符小寫。如:

UserService.java類中類名是UserService ,獲取bean默認名字就是userService

 也可以更改,如上面的UserRepositoryImpl類,用了@Repository("userRepository"),表示bean名字為userRepository

 

 在xml中,有一些屬性和節點:

 

 resource-pattern:只掃描特定文件

 context:include-filter: 子節點表示要包含的組件

 context:exclude-filter: 子節點表示要排除在外的組件

 

1      <!-- 可以通過resource-pattern指定掃描的資源 -->
2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"
3      resource-pattern="repository/*.class">
4      </context:component-scan>
5  

 

 這樣,只會掃描repository包下的類,如果main函數中,還要調用其他類,報錯。只能調用repository包下的類。

 

1     <!-- context:exclude-filter 子節點指定排除哪些指定表達式的組件 -->  
2      <context:component-scan base-package="package com.guigu.spring.beans.annotation">
3       <context:exclude-filter type="annotation" expression="package com.guigu.spring.beans.annotation.repository"/>  //type類型后面看
4      </context:component-scan>
5  

 

 

 這表示不掃描repository子包的文件,若main函數中調用它們,會拋異常

 

1      <!-- context:include-filter 子節點指定包含哪些指定表達式的組件, 該子節點需要use-default-filters配合使用 --> 
2      <context:component-scan base-package="package com.guigu.spring.beans.annotation"
3      use-default-filters="false">
4           <context:include-filter type="annotation" 
5             expression="package com.guigu.spring.beans.annotation"/> 
6      </context:component-scan>

 

注意,use-default-filters默認自動掃描全部,要設置成false不自動掃描,才能實現只掃描部分的功能。

 

<context:include-filter>和<context:exclude-filter>子節點支持多種類型的過濾表達式:

類別 示例 說明
annotation  com.yl.XxxAnnotation 所有標注了XxxAnnotation的類,該類型采用目標類是否標注了某個注解進行過濾
assinable  com.yl.XxxService 所有繼承或擴展XxxService的類,該類型采用了目標類是否繼承或擴展某個特定類進行過濾
aspectj  com.yl.*Service 所有類名義Service結束的類及繼承或擴展它們的類,該類型采用AspectJ表達式進行過濾
regex  com.yl.anno.* 所有com.yl.anno包下的類。該類型采用正則表達式,根據類的類名進行過濾
custom  com.yl.XxxTypeFilter  采用XxxTypeFilter通過代碼的方式定義過濾原則。該類必須實現org.springframewor

 

@Autowired自動裝配具有兼容類型的單個bean屬性。可以對類成員變量方法構造函數進行標注,完成自動裝配的工作。 通過 @Autowired的使用來代替set方法。(property 屬性通過調用setter方法進行賦值)

意思就是用它,可以代替xml中的<property name="car" ref="car"> 這樣的引用賦值。自動創建bean。

 

例子:Person類有Car對象,不用 自動裝配

 

 1    //Person類
 2 public class Person {    
 3     private Car car;
 4     
 5     public Car getCar() {
 6         return car;
 7     }
 8     public void setCar(Car car) {
 9         this.car = car;
10     }
11 }
 1     //Car類
 2 public class Car {
 3     private String brand;
 4     private double price;
 5     
 6     public void setBrand(String brand) {
 7         this.brand = brand;
 8     }
 9     public void setPrice(double price) {
10         this.price = price;
11     }
12 }

 

xml

1     <bean id="person" class="com.guigu.spring.bean.Person">     
2         <property name="car" ref="car"/>     
3     </bean>     
4     <bean id="car" class="com.guigu.spring.bean.Car">     
5         <property name="brand" value=" aodi"/>     
6         <property name="price" value="200000"/>     
7     </bean>     

 

main

1     ApplicationContext context = new ClassPathXmlApplicationContext("autowired.xml");  
2     Person person=(Person)ctx.getBean("person");
3     System.out.println(person);

 

這是之前的做法。

@Autowired自動裝配的方法

 

查了一下,在之前版本的Spring中,要使用@Autowired,要在xml寫上這一行代碼才行

1 <!-- 該 BeanPostProcessor 將自動對標注 @Autowired 的 Bean 進行注入 -->     
2   <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

但現在spring4,<context:component-scan>自動注冊AutowiredAnnotationBeanPostProcessor實例,可以使用@Autowired和@Resource、和@Inject注解(一般用@Autowired)

 所以,如果使用了<context:component-scan>,就不用額外注冊,不然還是要

1      //Person類
2   public class Person {    
3       //@Aotuwired   //自動根據xml配置實例car對象
4       private Car car;
5       
6  }

 

1      <bean id="person" class="com.guigu.spring.bean.Person">     
2     //這里就不需要再寫ref="car"  
3      </bean>     
4      <bean id="car" class="com.guigu.spring.bean.Car">     
5          <property name="brand" value=" aodi"/>     
6          <property name="price" value="200000"/>     
7      </bean>     

 

結果和不用 @Aotuwired一樣,都可以

 還可以寫在setter上

 1       //Person類
 2    public class Person {    
 3        private Car car;
 4         //@Aotuwired  
 5        public Car setCar(Car car){
 6              this.car=car;
 7                }
 8  }

 

 

回到注解上面的例子:

 1     //UserController.java
 2  package com.guigu.spring.beans.annotation.controller;
 3  import org.springframework.stereotype.Controller;
 4   
 5   @Controller
 6   public class UserController {
 7   
 8       public void execute(){
 9           System.out.println("UserController execute...");
10      }
11  }

 

 1    // main函數
 2   public class Main {
 3  
 4      public static void main(String[] args) {
 5          private UserController userController;
 6          ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
 7         userController.execute();  // 報錯
 8  }  
9
}

 

在main函數聲明userController然后直接調用它的方法,這樣顯然不行,因為userController都還沒有創建,這時用@Autowired就很簡單

 1      // main函數
 2     public class Main {
 3    
 4        public static void main(String[] args) {
 5            //@Autowired
 6            private UserController userController;
 7            ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
 8            userController.execute();//不報錯
 9    }  
10   }

 

這樣,就自動配置創建了userController對象,可以直接使用

注意①:@Autowired要想成功配置,得先掃描得到,就是UserController類一定要能被掃描到。

注意②:@Autowired遇到相同兩個類

 

 

 1          //UserRepository
 2     package com.guigu.spring.beans.annotation.repository;
 3     public interface UserRepository {
 4         
 5         void save();
 6     }
 7     
 8         //UserRepositoryImpl  繼承 UserRepository
 9     package com.guigu.spring.beans.annotation.repository;
10   import org.springframework.stereotype.Repository;
11   
12   @Repository("userRepository");   //這里
13   public class UserRepositoryImpl implements UserRepository {
14   
15       @Override
16       public void save() {
17           System.out.println("UserRepositoryImpl Save...");
18       }
19    //UserRepositoryImpl2  繼承 UserRepository
20    @Repository
21    public class UserRepositoryImpl2 implements UserRepository {
22   
23       @Override
24      public void save() {
25           System.out.println("UserRepositoryImpl2 Save...");
26       }
27   }

 

 1        // main函數
 2       public class Main {
 3      
 4          public static void main(String[] args) {
 5              //@Autowired
 6              private UserRepository userRepository ;
 7              ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
 8              userRepository .save();
 9      }  
10    }

 

main函數中有@Autowired,自動創建對象,但UserRepository 類卻有兩個接口,它要去創建哪一個呢?

 :默認情況下,若有兩個,去找名字相同的,就是還沒實例的這個userRepository ,若找到和它名字一樣的,上面 @Repository("userRepository"); 寫了名字,那就找它了。

 若不是這樣寫@Repository("userRepository");而是 @Repository(),那就報錯了。

注意③:解決②的另一個方法

 若@Repository("userRepository");改成@Repository(),main函數會報錯。

 改一下main函數

 1          // main函數
 2         public class Main {
 3        
 4            public static void main(String[] args) {
 5                //@Autowired
 6                //Qualifier("userRepositoryImpl ")
 7                private UserRepository userRepository ;
 8                ApplicationContext ctx =new ClassPathXmlApplicationContext("beans-annotation.xml");         
 9                userRepository .save();
10        }  
11     }

 

Qualifier("userRepositoryImpl ");表示去找userRepositoryImpl 實例,這樣也解決了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM