spring基礎之三->SpringIOC的註解應用

SpringIOC的註解應用

在以前的項目中,咱們都是經過xml文件進行bean或者某些屬性的賦值,其實還有另一種註解的方式,在企業開發中使用的不少,在bean上添加註解,能夠快速的將bean註冊到ioc容器。java

一、使用註解的方式註冊bean到IOC容器中

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.or...
http://www.springframework.or...
http://www.springframework.or...">

<!--
若是想要將自定義的bean對象添加到IOC容器中,須要在類上添加某些註解
Spring中包含4個主要的組件添加註解:
@Controller:控制器,推薦給controller層添加此註解
@Service:業務邏輯,推薦給業務邏輯層添加此註解
@Repository:倉庫管理,推薦給數據訪問層添加此註解
@Component:給不屬於以上基層的組件添加此註解
注意:咱們雖然人爲的給不一樣的層添加不一樣的註解,可是在spring看來,能夠在任意層添加任意註解
spring底層是不會給具體的層次驗證註解,這樣寫的目的只是爲了提升可讀性,最偷懶的方式
就是給全部想交由IOC容器管理的bean對象添加component註解

使用註解須要以下步驟:
一、添加上述四個註解中的任意一個
二、添加自動掃描註解的組件,此操做須要依賴context命名空間
三、添加自動掃描的標籤context:component-scan

注意:當使用註解註冊組件和使用配置文件註冊組件是同樣的,可是要注意:
一、組件的id默認就是組件的類名首字符小寫,若是非要更名字的話,直接在註解中添加便可
二、組件默認狀況下都是單例的,若是須要配置多例模式的話,能夠在註解下添加@Scope註解
-->
<!--
定義自動掃描的基礎包:
base-package:指定掃描的基礎包,spring在啓動的時候會將基礎包及子包下全部加了註解的類都自動
掃描進IOC容器
-->
<context:component-scan base-package="com.mashibing"></context:component-scan>
</beans>spring

PersonController.java

package com.mashibing.controller;
​
import org.springframework.stereotype.Controller;
​
@Controller
public class PersonController {
 public PersonController() {
 System.out.println("建立對象");
 }
}

PersonService.java

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 {
}

二、定義掃描包時要包含的類和不要包含的類

當定義好基礎的掃描包後,在某些狀況下可能要有選擇性的配置是否要註冊bean到IOC容器中,此時能夠經過以下的方式進行配置。sql

applicationContext.xmlexpress

<?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.or...
http://www.springframework.or...
http://www.springframework.or...">
<context:component-scan base-package="com.mashibing" use-default-filters="false">
<!--
當定義好基礎掃描的包以後,能夠排除包中的某些類,使用以下的方式:
type:表示指定過濾的規則
annotation:按照註解進行排除,標註了指定註解的組件不要,expression表示要過濾的註解
assignable:指定排除某個具體的類,按照類排除,expression表示不註冊的具體類名
aspectj:後面講aop的時候說明要使用的aspectj表達式,不用
custom:定義一個typeFilter,本身寫代碼決定哪些類被過濾掉,不用
regex:使用正則表達式過濾,不用
-->
<!--       <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>-->

<!--指定只掃描哪些組件,默認狀況下是所有掃描的,因此此時要配置的話須要在component-scan標籤中添加 use-default-filters="false"-->
<context:include-filter type="assignable" expression="com.mashibing.service.PersonService"/>
</context:component-scan>
</beans>app

三、使用@AutoWired進行自動注入

使用註解的方式實現自動注入須要使用@AutoWired註解。框架

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 personService;
​
 public PersonController() {
 System.out.println("建立對象");
 }
​
 public void getPerson(){
 personService.getPerson();
 }
}

PersonService.java

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.java

package com.mashibing.dao;
​
 import org.springframework.stereotype.Repository;
​
@Repository
public class PersonDao {
​
 public void getPerson(){
 System.out.println("PersonDao:getPerson");
 }
}

注意:當使用AutoWired註解的時候,自動裝配的時候是根據類型實現的。學習

一、若是隻找到一個,則直接進行賦值,prototype

二、若是沒有找到,則直接拋出異常,code

三、若是找到多個,那麼會按照變量名做爲id繼續匹配,

一、匹配上直接進行裝配

二、若是匹配不上則直接報異常

PersonServiceExt.java

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註解來指定id的名稱,讓spring不要使用變量名,當使用@Qualifier註解的時候也會有兩種狀況:

一、找到,則直接裝配

二、找不到,就會報錯

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();
 }
}

經過上述的代碼咱們可以發現,使用@AutoWired確定是可以裝配上的,若是裝配不上就會報錯。

四、@AutoWired能夠進行定義在方法上

當咱們查看@AutoWired註解的源碼的時候發現,此註解不只可使用在成員變量上,也可使用在方法上。

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);
//        personServiceExt2.getPerson();
 }
​
 /**
 * 當方法上有@AutoWired註解時:
 *  一、此方法在bean建立的時候會自動調用
 *  二、這個方法的每個參數都會自動注入值
 * @param personDao
 */
 @Autowired
 public void test(PersonDao personDao){
 System.out.println("此方法被調用:"+personDao);
 }
 
 /**
 * @Qualifier註解也能夠做用在屬性上,用來被看成id去匹配容器中的對象,若是沒有
 * 此註解,那麼直接按照類型進行匹配
 * @param personService
 */
 @Autowired
 public void test2(@Qualifier("personServiceExt") PersonService personService){
 System.out.println("此方法被調用:"+personService);
 }
}

五、自動裝配的註解@AutoWired,@Resource

在使用自動裝配的時候,出了可使用@AutoWired註解以外,還可使用@Resource註解,你們須要知道這兩個註解的區別。

一、@AutoWired:是spring中提供的註解,@Resource:是jdk中定義的註解,依靠的是java的標準

二、@AutoWired默認是按照類型進行裝配,默認狀況下要求依賴的對象必須存在,@Resource默認是按照名字進行匹配的,同時能夠指定name屬性。

三、@AutoWired只適合spring框架,而@Resource擴展性更好

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;
​
import javax.annotation.Resource;
​
@Controller
public class PersonController {
​
 @Qualifier("personService")
 @Resource
 private PersonService personServiceExt2;
​
 public PersonController() {
 System.out.println("建立對象");
 }
​
 public void getPerson(){
 System.out.println("personController..."+personServiceExt2);
 personServiceExt2.getPerson();
 }
​
 /**
 * 當方法上有@AutoWired註解時:
 *  一、此方法在bean建立的時候會自動調用
 *  二、這個方法的每個參數都會自動注入值
 * @param personDao
 */
 @Autowired
 public void test(PersonDao personDao){
 System.out.println("此方法被調用:"+personDao);
 }
​
 /**
 * @Qualifier註解也能夠做用在屬性上,用來被看成id去匹配容器中的對象,若是沒有
 * 此註解,那麼直接按照類型進行匹配
 * @param personService
 */
 @Autowired
 public void test2(@Qualifier("personServiceExt") PersonService personService){
 System.out.println("此方法被調用:"+personService);
 }
}

六、泛型依賴注入

爲了講解泛型依賴注入,首先咱們須要先寫一個基本的案例,按照咱們以前學習的知識:

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("保存老師");
 }
}

StudentService.java

package com.mashibing.service;
​
import com.mashibing.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
@Service
public class StudentService {
​
 @Autowired
 private StudentDao studentDao;
​
 public void save(){
 studentDao.save();
 }
}

TeacherService.java

package com.mashibing.service;
​
import com.mashibing.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
@Service
public class TeacherService {
 @Autowired
 private TeacherDao teacherDao;
​
 public void save(){
 teacherDao.save();
 }
}

MyTest.java

import com.mashibing.service.StudentService;
import com.mashibing.service.TeacherService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
​
import javax.sql.DataSource;
import java.sql.SQLException;
​
public class MyTest {
 public static void main(String[] args) throws SQLException {
 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
 StudentService studentService = context.getBean("studentService",StudentService.class);
 studentService.save();
​
 TeacherService teacherService = context.getBean("teacherService",TeacherService.class);
 teacherService.save();
 }
}

上述代碼是咱們以前的能夠完成的功能,可是能夠思考,Service層的代碼是否可以改寫:

BaseService.java

package com.mashibing.service;
​
import com.mashibing.dao.BaseDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
public class BaseService<T> {
 
 @Autowired
 BaseDao<T> baseDao;
 
 public void save(){
 System.out.println("自動注入的對象:"+baseDao);
 baseDao.save();
 }
}

StudentService.java

package com.mashibing.service;
​
import com.mashibing.bean.Student;
import com.mashibing.dao.StudentDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
@Service
public class StudentService extends BaseService<Student> {
​
}

TeacherService.java

package com.mashibing.service;
​
import com.mashibing.bean.Teacher;
import com.mashibing.dao.TeacherDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
​
@Service
public class TeacherService extends BaseService<Teacher>{
​
}
相關文章
相關標籤/搜索