1.准備工作
(1)導入jar包
除了上篇文章使用到的基本jar包外,還得加入aop的jar包,所有jar包如下
(2)配置xml
<?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.xsd"> <!-- 開啟注解掃描,到包里面掃描類、屬性、方法上是否有注解 --> <context:component-scan base-package="com.codeliu"/> </beans>
2.注解實例化Bean
(1)實例化Bean有四個注解
- @Component
- @Service:業務層
- @Controller:WEB層
- @Repository:持久層
雖然分了層,但目前這四個注解的功能是一樣的。
@Service(value = "user") //相當於bean標簽中的id,四種方式功能一樣 // @Component(value = "user") // @Controller(value = "user") // @Repository(value = "user") @Scope(value = "singleton") public class User { public void print() { System.out.println("user......"); } }
@Test /** * 使用注解實例化User類 */ public void testUser() { // 讀取配置文件 @SuppressWarnings("resource") ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); User user = (User)context.getBean("user"); user.print(); }
bean的作用域配置
Spring中可以使用scope屬性來配置bean的作用域:
singleton:單例,在初始化配置文件時生成單例bean對象
prototype:原型的,在初始化配置文件時不生成bean對象,使用時返回不同的bean對象
request:web環境下每一個request請求都會返回一個不同的bean,只在本次請求中有效
session:web環境下每一個request請求都會返回一個不同的bean,在session中有效
3.注解為屬性賦值
首先來個UserDao
@Component(value = "userDao") public class UserDao { public void print() { System.out.println("userdao......"); } }
再來個service
@Service(value = "userService") public class UserService { // 注入對象類型的屬性,不用提供set方法 // 1.使用自動裝配 // @Autowired // 為byType類型,如果有多個相同類型的,得配合@Qualifier注解 // private UserDao userDao; // 2.不使用自動裝配 @Resource(name = "userDao") private UserDao userDao; // 注入普通類型的屬性 @Value(value = "CodeTiger") private String name; public void print() { System.out.println("UserService......"); userDao.print(); System.out.println(name); } }
為屬性賦值,我們可以使用自動裝配,也可以手動賦值。
@Test /** * 使用注解注入屬性 */ public void testUserService() { @SuppressWarnings("resource") ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml"); UserService service = (UserService)context.getBean("userService"); service.print(); }
4.注解和xml結合使用
當然我們也可以同時使用注解和xml,一般我們在xml中實例化Bean,使用注解為屬性賦值。
Spring@Autowired注解與自動裝配
1 配置文件的方法
我們編寫spring 框架的代碼時候。一直遵循是這樣一個規則:所有在spring中注入的bean 都建議定義成私有的域變量。並且要配套寫上 get 和 set方法。
|
Boss 擁有 Office 和 Car 類型的兩個屬性: System.out.println必須實現toString方法 我們在 Spring 容器中將 Office 和 Car 聲明為 Bean,並注入到 Boss Bean 中:下面是使用傳統 XML 完成這個工作的配置文件 beans.xml: 清單 4. beans.xml 將以上三個類配置成 Bean 當我們運行以下代碼時,控制台將正確打出 boss 的信息: 清單 5. 測試類:AnnoIoCTest.java 這說明 Spring 容器已經正確完成了 Bean 創建和裝配的工作。
|
2 @Autowired
Spring 2.5 引入了 @Autowired 注釋,它可以對類成員變量、方法及構造函數進行標注,完成自動裝配的工作。 通過 @Autowired的使用來消除 set ,get方法。
要實現我們要精簡程序的目的。需要這樣來處理:
* 在applicationContext.xml中加入:
Spring 通過一個 BeanPostProcessor 對 @Autowired 進行解析,所以要讓 @Autowired 起作用必須事先在 Spring 容器中聲明 AutowiredAnnotationBeanPostProcessor Bean。
* 修改在原來注入spirng容器中的bean的方法。
在域變量上加上標簽@Autowired,並且去掉 相應的get 和set方法
清單 6. 使用 @Autowired 注釋的 Boss.java
* 在applicatonContext.xml中 把原來 引用的<porpery >標簽也去掉。
這樣,當 Spring 容器啟動時,AutowiredAnnotationBeanPostProcessor 將掃描 Spring 容器中所有 Bean,當發現 Bean 中擁有 @Autowired 注釋時就找到和其匹配(默認按類型匹配)的 Bean,並注入到對應的地方中去。
按照上面的配置,Spring 將直接采用 Java 反射機制對 Boss 中的 car 和 office 這兩個私有成員變量進行自動注入。所以對成員變量使用 @Autowired 后,您大可將它們的 setter 方法(setCar() 和 setOffice())從 Boss 中刪除。
當然,您也可以通過 @Autowired 對方法或構造函數進行標注,如果構造函數有兩個入參,分別是 bean1 和 bean2,@Autowired 將分別尋找和它們類型匹配的 Bean,將它們作為 CountryService (Bean1 bean1 ,Bean2 bean2) 的入參來創建 CountryService Bean。來看下面的代碼: 對方法
這時,@Autowired 將查找被標注的方法的入參類型的 Bean,並調用方法自動注入這些 Bean。而下面的使用方法則對構造函數進行標注:
由於 Boss() 構造函數有兩個入參,分別是 car 和 office,@Autowired 將分別尋找和它們類型匹配的 Bean,將它們作為 Boss(Car car ,Office office) 的入參來創建 Boss Bean。
Spring注解:自動注入屬性(@Resource、@Autowired、@Qualifier )
先寫一個場景,舉例說明:
1、接口:IAnimal
public Interface IAnimal{ ...... }
2、實現類:DogImpl ,實現了IAnimal接口。
@Service("dogImpl")
public class DaoImpl impliments IAnimal{
...
}
3、業務類:AnimalController
public class AnimalController { @Autowired private IAnimal dogImpl; ...... }
假如有一個“動物”的接口 IAnimal, DogImpl類實現了接口 IAnimal, 且該接口只有 DogImpl這一個實現類,那么在引用實現類的時候,我們使用的是實現類的接口(像上面程序展示的那樣)。Spring會按 byType的方式尋找接口的實現類,將其注入。
假如有另一個實現類 CatImpl 也實現了接口 IAnimal, 這時候再按上面的方式去引用, 在同時存在兩個實現類的情況下,會出現什么情況呢?
答:會報錯。 這是由於 @Autowired 的特性決定的: @Autowired 的注入方式是 byType 注入, 當要注入的類型在容器中存在多個時,Spring是不知道要引入哪個實現類的,所以會報錯。
那么在同一類型擁有多個實現類的時候,如何注入呢?
答:這種場景下,只能通過 byName 注入的方式。可以使用 @Resource 或 @Qualifier 注解。
@Resource 默認是按照 byName 的方式注入的, 如果通過 byName 的方式匹配不到,再按 byType 的方式去匹配。所以上面的引用可以替換為:
public class AnimalController { @Resource(name="dogImpl") //實現類1中 @Service注解中標定的名稱 private IAnimal dogImpl; ...... }
@Qualifier 注解也是 byName的方式,但是與@Resource 有區別,@Qualifier 使用的是 類名。
public class AnimalController { @Qualifier("DaoImpl") //實現類1的類名。注意區分與@Resource(name="dogImpl") 的區別。 private IAnimal dogImpl; ...... }
總結:
1、@Autowired 是通過 byType 的方式去注入的, 使用該注解,要求接口只能有一個實現類。
2、@Resource 可以通過 byName 和 byType的方式注入, 默認先按 byName的方式進行匹配,如果匹配不到,再按 byType的方式進行匹配。
3、@Qualifier 注解可以按名稱注入, 但是注意是 類名。
附:https://www.jianshu.com/p/80df0a6daf65
https://blog.csdn.net/l1212xiao/article/details/80424064
