1. 程式人生 > >Spring對IOC的理解

Spring對IOC的理解

配置文件 efault custom span .cn mvc 方式 9.png 特定

一、IOC控制反轉和DI依賴註入

  1.控制反轉,字面可以理解為:主動權的轉移,原來一個應用程序內的對象是類通過new去主動創建並實例化的,對對像創建的主動權在程序代碼中。程序不僅要管理業務邏輯也要管理對的象創建和依賴關系。這是很累的,也跟軟件工程 "低耦合高內聚" 的概念不十分符合。

  技術分享

  有了spring的ioc容器之後,對象的實例化和依賴關系管理都由IOC容器進行統一管理,主體類只要依賴ioc容器就夠了,需要啥,容器會給他註入進去,也就是只要聲明對象不用再主動去new,ioc容器幫忙把相應的對象註入到聲明對象中,使其變成實例化對象。(類似主體類提供一個軀體,ioc容器把靈魂註入進去,使其變成一個生命體,激活他),這樣創建對象的主動權就轉移交接了,

  技術分享

二、使用xml配置方式實現IOC

  1.在ioc容器中配置了dao實現類和service類的bean,在容器加載的時候就會實例化這些bean到內存中。(bean.xml配置如下)

 1 <beans xmlns="http://www.springframework.org/schema/beans"
 2        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3        xsi:schemaLocation="http://www.springframework.org/schema/beans
 4        http://www.springframework.org/schema/beans/spring-beans.xsd
5 "> 6 7 <!-- BookDao Bean --> 8 <bean id="bookDao" class="com.study.DaoImpl.BookDaoImpl"></bean> 9 10 <!-- BookService Bean--> 11 <bean id="bookService" class="com.study.Service.BookService"> 12 <!-- BookService中的聲明了BookDao對象,通過ref屬性將BookDao的bean註入到對象中
--> 13 <property name="bookDao" ref="bookDao"/> 14 </bean> 15 </beans>

  2. service類中需要用到dao類的實例(正常情況下需要new一個dao類對象),但是用ioc容器接管後只需要聲明dao接口對象即可,然後寫一個dao對象的set方法。(要註入的對象必須要有set方法,否則將報錯 Bean property ‘bookDao‘ is not writable or has an invalid setter method)因為spring註入是根據反射機制實現的,他在反射註入的時候會調用該方法名的set方法,如果set方法寫錯,或者根本沒寫,那麽註入就會失敗。(BookService類如下)

 1 public class BookService {
 2     private BookDao bookDao;
 3 
 4     public BookService() {
 5         System.out.println("BookService實例化");
 6     }
 7 
 8     public void setBookDao(BookDao bookDao) {
 9         System.out.println("BookService屬性初始化裝配成功");
10         this.bookDao = bookDao;
11     }
12 
13     public void storeBook(String bookname){
14         System.out.println("圖書上架");
15         System.out.println(bookDao.addBook(bookname));
16     }
17 }

  如上代碼:BookSerivce類需要用到BookDao對象,但是卻沒有new對象,只有一個set方法,這個set方法就是ioc容器註入的入口必不可少),

  3.此處我們用ApplicationContext作為容器,初始化配置文件,然後從容器中根據id名取出容器中已經幫我們實例化好的對象。

 1 public class TestDmeo {
 2     BookService bookService;
 3 
 4     @Test
 5     public void testStoreBook(){
 6         System.out.println("容器初始化");
 7         ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
 8         bookService = (BookService) app.getBean("bookService");//將對象註入到聲明好的BookService對象中。(bookService就是配置文件中的id)
 9         bookService.storeBook("Spring MVC");
10     }
11 }

  getBean中的參數就是配置文件中的bean的id名,這個id在spring進行反射實例化的時候,相當於實例化對象的名稱:

   技術分享

   4.dao類和實現類如下:

接口類:

1 public interface BookDao {
2     public String addBook(String BookName);
3 }

實現類:

 1 public class BookDaoImpl implements BookDao {
 2 
 3     public BookDaoImpl() {
 4         System.out.println("BookDao實例化");
 5     }
 6 
 7     public String addBook(String BookName) {
 8         return BookName+"添加成功";
 9     }
10 }

  5.運行測試結果:

  技術分享

 6.大體思路如下圖:

技術分享

  程序中除了初始化容器用了new對象,其余的基本沒有new的存在。

二、註解方式配置IOC

  註解配置方式目的和xml配置的目的一樣,都是為了實現bean的創建。常用的註解如下:

      • @Component 在類定義之前添加@Component註解,他會被spring容器識別,並轉為bean。
      • @Repository 對Dao實現類進行註解 (特殊的@Component)
      • @Service 用於對業務邏輯層進行註解, (特殊的@Component)
      • @Controller 用於控制層註解 , (特殊的@Component)

  

  裝配註解如下:

      • @Autowired 默認按照類型裝配註入,想按照名稱來裝配的話要結合@Qualifier(“name”)一起使用,使用@Autowired註解可以不用set方法。@Autowired 註釋進行自動註入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個
      • @Qualifier("name") 中的name是bean的名字,也就是id,和@Autowired可以作為限定專配對象的名稱
      • @Resource 默認按照名稱裝配註入,當找不到對應名成的bean的時候就按照類型匹配,如果還是找不到的話就會報錯,@Autowired是spring提供的,@Resource是javaee提供,使用@Resource可以減少對spring的依賴

  範例:

  1.例子同上,只是配置bean的方式從xml文件中轉移到了代碼中,用註解體現。

  技術分享

  2.除了把配置文件中<bean id="" class=""/>變成對應的註解外,另外一個區別在於,bean.xml文件中的修改,需要做如下,配置才能夠使註解生效

  技術分享

  context的配置有如下方法:

  1.僅掃描特定包下的特定類

1 <context:component-scan base-package="com.study" resource-pattern="Service/B*.class"/>

  這是掃描Service包下B開頭的所有類。

  2.使用<context:include-filter .../>和<context:exclude-filter .../>配置那些需要和不需要的掃描的包

Filter Type Examples Expression Description
annotation org.example.SomeAnnotation 符合SomeAnnoation的target class(註解類)
assignable org.example.SomeClass 指定class或interface的全名(指定確切的類或接口)
aspectj org.example..*Service+ AspectJ語法
regex org\.example\.Default.* Regelar Expression  (正則表達式)
custom org.example.MyTypeFilter Spring3新增自定義Type,org.springframework.core.type.TypeFilter

1 <!-- 容器掃描包下的註解配置組件 -->
2        <context:component-scan base-package="com.study" use-default-filters="false">
3               <context:include-filter type="aspectj" expression="com.study.Service.*"/> <!-- 模糊過濾 -->
4               <context:include-filter type="annotation" expression="org.springframework.stereotype.Component"/><!-- 過濾指定的註解 -->
5               <context:include-filter type="assignable" expression="com.study.Service.BookService"/><!-- 過濾指定的類或接口,路徑要完整,如果是接口的話,所有派生類都會被過濾 -->
6               <context:include-filter type="regex" expression="com.*"/>
7        </context:component-scan>

  <context:exclude-filter ../>要配在<context:include-filter .../>的後面。

Spring對IOC的理解