1 使用JUnit
- 添加pom依賴
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
- 在方法上使用@Test註解,方法就可以被直接執行
- 給測試類起名字時,千萬不要定義成Test
- 測試類必須放在test包內
- 測試方法不能是static、不能有參數、不能有返回值
2 註冊bean到IOC容器中
- xml完整、全面,但註解的方式更快
- 如果想要將自定義的bean對象添加到IOC容器中,完成註冊bean的功能,就需要在類上添加某些註解
- @Controller:用於將控制層對象添加到IOC容器
- @Service:用於將業務邏輯對象添加到IOC容器
- @Repository:用於將數據訪問層對象添加到IOC容器
- @Component:給不屬於以上幾層的bean添加到IOC容器
- 我們雖然人爲的給不同的層添加不同的註解,但是在spring運行過程中,不會對這四個註解做任何區分,可以在任意層添加任意註解,提供了四個不同的註解只是爲了提高可讀性,實際開發中,最好能區分
- 使用註解需要如下步驟
- 添加上述四個註解中的任意一個
- 添加context命名空間
- 添加自動掃描的標籤context:component-scan,和指定掃描的基礎包base-package,默認情況下,spring會在啓動的時候會將基礎包及子包下,所有加了任意註解的類都自動掃描進IOC容器
<?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.mashibing"></context:component-scan>
</beans>
- bean的id默認就是組件的類名首字符小寫,如果非要改名字的話,需要在註解中添加參數值value
@Controller(value = "person")
public class PersonController
- 組件默認情況下都是單例的,如果需要配置多例模式的話,可以在註解下添加@Scope註解,並將其value屬性設置爲prototype
@Controller(value = "person")
@Scope(value = "prototype")
public class PersonController
- PersonController
package com.mashibing.controller;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
public PersonController() {
System.out.println("創建對象");
}
}
- PersonService
package com.mashibing.service;
import org.springframework.stereotype.Service;
@Service
public class PersonService {
}
- PersonDao.java
package com.mashibing.dao;
import org.springframework.stereotype.Repository;
@Repository("personDao")
@Scope(value="prototype")
public class PersonDao {
}
3 定義掃描包時要包含的類和不要包含的類
- component-scan的幾個屬性
- base-package:Spring將掃描的基礎package名,Spring會掃描該包以及其子孫包下的所有類
- use-default-filters:默認爲true,會將@Component、@Repository、@Service、@Controller修飾的類都自動實例化爲bean,並將其添加到IOC容器中,如果設置爲false,所有註釋的類都不實例化,可以理解爲默認使用一個可以允許所有註釋生效的include-filter
- include-filter:指定掃描時需要實例化的類型,我們可以從名字看到這是一個Filter,你可以自己定義該Filter,Spring爲我們提供了一套方便的實現,我們可以根據標註、類、包等相關信息決定當掃描到該類時是否需要實例化該類,需要注意的是如果你僅僅想掃描如@Controller不僅要加includeFilters,還需要將useDefaultFilters設置爲false
- exclude-filter:指定掃描到某個類時需要忽略它,實現和上一個Filter一樣,區別只是如果Filter匹配,Spring會忽略該類
- 首先通過exclude-filter 進行黑名單過濾,然後通過include-filter 進行白名單過濾,剩餘排除,但要注意的是,設置了use-default-filters爲true,就相當於已經設定了如下幾個include-filter
<context:component-scan base-package="com.mashibing" use-default-filters="false">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/>
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>
- 一般實際開發使用exclude-filter較多,include-filter基本不用。如果引入的第三方包中某些類被@Component、@Repository、@Service、@Controller外的註解修飾,而我們又想將這些類交給Spring管理,此時就需要使用include-filter功能
- include-filtery與include-filter中的type屬性表示過濾規則
- annotation:按照註解進行排除,標註了指定註解的組件不要,expression表示要過濾的註解的全限定名
- assignable:指定排除某個具體的類,按照類排除,expression表示不註冊的具體類名,不能寫*,如果想寫多個,只能寫多條排除
- aspectj:後面講aop的時候說明要使用的aspectj表達式,不用
- custom:定義一個typeFilter,自己寫代碼(繼承某個類)決定哪些類被過濾掉,不用
- regex:使用正則表達式過濾,不用
- applicationContext.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.mashibing" use-default-filters="false">
<context:include-filter type="assignable" expression="com.mashibing.service.PersonService"/>
</context:component-scan>
</beans>
4 在屬性上使用@AutoWired進行自動注入
- 下面的實驗,主要實驗向PersonController中,注入不同的PersonService實例
- 使用AutoWired註解的時候,自動裝配的時候是根據類型實現的
- 如果只找到一個,則直接進行賦值
- 如果一個都沒找到(例如:需要注入的類存在,但該類沒被@Service註釋,也就是該類對應的bean沒由spring容器管理),則直接拋出異常
- 如果找到多個(例如PersonService 和PersonServiceExt兩個類之間是繼承關係,它們都是PersonService類型,而PersonController用的是PersonService類型定義的變量),此時會用PersonController類中變量名,查找容器中是否有與其同名的bean,如果找到了就進行裝配,找不到還是會報錯
- 使用@AutoWired與使用xml自動裝配不同
- @AutoWired是一定能夠裝配上的,因爲裝配不上就會報錯,而xml允許裝配不上,不會報錯,而是將該屬性值賦爲null
- @AutoWired是根據反射注入的,即使沒有setter方法,屬性也能注入成功,而xml方式中的byType和byName是通過setter方法注入的(constructor不是),沒有setter方法無法注入成功
- PersonController
package com.mashibing.controller;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Autowired
private PersonService personService;
public PersonController() {
System.out.println("創建對象");
}
public void getPerson(){
personService.getPerson();
}
}
- PersonService
package com.mashibing.service;
import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonService {
@Autowired
private PersonDao personDao;
public void getPerson(){
personDao.getPerson();
}
}
- PersonDao
package com.mashibing.dao;
import org.springframework.stereotype.Repository;
@Repository
public class PersonDao {
public void getPerson(){
System.out.println("PersonDao:getPerson");
}
}
- PersonServiceExt:用於測試有兩個相同類型相同的bean對象
package com.mashibing.service;
import com.mashibing.dao.PersonDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class PersonServiceExt extends PersonService{
@Autowired
private PersonDao personDao;
public void getPerson(){
System.out.println("PersonServiceExt......");
personDao.getPerson();
}
}
- PersonController.java
package com.mashibing.controller;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Autowired
private PersonService personServiceExt;
public PersonController() {
System.out.println("創建對象");
}
public void getPerson(){
personServiceExt.getPerson();
}
}
- 還可以使用@Qualifier註解,來指定當@AutoWired按類型找到多個bean時,不通過變量名與bean的id進行匹配,而是使用@Qualifier中的value值,與bean中id進行匹配
- PersonController.java
package com.mashibing.controller;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Autowired
@Qualifier("personService")
private PersonService personServiceExt2;
public PersonController() {
System.out.println("創建對象");
}
public void getPerson(){
personServiceExt2.getPerson();
}
}
5 在方法上使用@AutoWired
- 當我們查看@AutoWired註解的源碼的時候發現,此註解不僅可以使用在成員變量上,也可以使用在方法上
- 當方法上有@AutoWired註解時
- 此方法在bean創建的時候會自動調用
- 這個方法的每一個參數都會自動注入值,默認按照類型進行匹配
- @Qualifier註解也可以用在形參上,可以指定參數去匹配容器中指定id的bean
- PersonController.java
package com.mashibing.controller;
import com.mashibing.dao.PersonDao;
import com.mashibing.service.PersonService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
@Controller
public class PersonController {
@Qualifier("personService")
@Autowired
private PersonService personServiceExt2;
public PersonController() {
System.out.println("創建對象");
}
public void getPerson(){
System.out.println("personController..."+personServiceExt2);
}
@Autowired
public void test(PersonDao personDao){
System.out.println("此方法被調用:"+personDao);
}
@Autowired
public void test2(@Qualifier("personServiceExt") PersonService personService){
System.out.println("此方法被調用:"+personService);
}
}
6 自動裝配的註解@AutoWired,@Resource間區別
- 在使用自動裝配的時候,除了可以使用@AutoWired註解之外,還可以使用@Resource註解
- 二者區別
- @AutoWired是spring中提供的註解,@Resource:是jdk中定義的註解,依靠的是java的標準
- @AutoWired默認是按照類型進行裝配,如果需要按名稱裝配,需要與@Qualifier協同使用,且默認情況下要求依賴的對象必須存在,如果允許不存在需要將其required屬性設置爲false,@Resource默認是按照名字進行裝配的,名稱默認使用屬性名,也可以通過name屬性進行指定,名找不到再按type找,但要注意一旦設定了name屬性,就只能按名字裝配
- @AutoWired只能在spring框架中使用,而@Resource可以在其他框架中使用,擴展性更好
7 泛型依賴注入
- 自動注入時,如果屬性類型中存在泛型,默認會按類型+泛型一同進行裝配
- Student.java
package com.mashibing.bean;
public class Student {
}
- Teacher.java
package com.mashibing.bean;
public class Teacher {
}
- BaseDao.java
package com.mashibing.dao;
import org.springframework.stereotype.Repository;
@Repository
public abstract class BaseDao<T> {
public abstract void save();
}
- StudentDao.java
package com.mashibing.dao;
import com.mashibing.bean.Student;
import org.springframework.stereotype.Repository;
@Repository
public class StudentDao extends BaseDao<Student>{
public void save() {
System.out.println("保存學生");
}
}
- TeacherDao.java
package com.mashibing.dao;
import com.mashibing.bean.Teacher;
import org.springframework.stereotype.Repository;
@Repository
public class TeacherDao extends BaseDao<Teacher> {
public void save() {
System.out.println("保存老師");
}
}
- MyService.java
package com.mashibing.service;
import com.mashibing.bean.Teacher;
import com.mashibing.dao.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@Autowired
private BaseDao<Teacher> studentDao;
public void save() {
studentDao.save();
}
}
- MyTest.java
package com.mashibing.bean;
import com.mashibing.service.MyService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.sql.SQLException;
public class MyTest {
public static void main(String[] args) throws SQLException {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyService studentService = context.getBean("myService", MyService.class);
studentService.save();
}
}