1、Spring3核心技術-IoC(一)

簡介:SpringIoc主要決議的問題就是Bean 的實例化和依賴問題,我們可以將Bean的實例化工作交給Spring進行管理這樣我們就不需要在到處new對象了,這只是一個小方面重要的是Spring幫助我們解決了Bean依賴的問題,也就是耦合問題,淡然我們希望我們的程序各個模塊甚至是功能在代碼上耦合度越低越好,Spring幫我們做了很大的優化。此文環境爲Spring3.2。

Spring對於Context和Bean的配置可以使用不同方式,這裏採用xml加annotation的形式進行後面會總結說一下spring的Context和Bean的配置方式:

1:簡單的使用Spring創建的Bean

2:Spring3 Ioc容器

3:Spring中Bean的配置和屬性

4:Spring Ioc和J2EE CDI

1:簡單的使用Spring創建的Bean

1.1:引入Spring3相關jar文件【這個測試中並不會用到所有jar這裏簡單起見引入所有jar,後面會簡要介紹些部分jar提供的功能】

1.2:在源碼包下添加Spring的初始化文件beans.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="org.fp.smark.spring3"></context:component-scan>  //Spring會在這裏定位你的Bean
</beans>
這裏beans.xml作爲初始文件,文件名是可以更改的,也可以有多個同類型的xml後面會介紹。

1.3:測試Spring IoC容器

MainService.java :我們自己的Bean,

package org.fp.smark.spring3;

import org.springframework.stereotype.Service;

@Service("mainService")
public class MainService {
	
	public void hello(){
		System.out.println("hello m Service");
	}
}
IOCTest.java :測試類
package org.fp.smark.spring3;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IOCTest {
	
	ApplicationContext context  = new ClassPathXmlApplicationContext("beans.xml");
	
	@Test
	public void test1(){
		MainService service = context.getBean("mainService",MainService.class);
		service.hello();
	}
}

context:ApplicationContext的實例,你在beans.xml中做的所有配置都會在Spring的容器中進行配置和映射,這裏也包括通過註解進行的配置,ApplicationContext是你接入Spring容器的入口;當然Spring的設計肯定不會簡單到值通過這一個類來作爲初始化入口,後面會介紹Spring在配置文件相關的內容和初始化Spring環境的一些內容。

2:Spring3 Ioc容器

你可以將Spring Ioc容器想象成是我們應用程序的一個大的上下文環境,我們所有通過Spring配置的Bean都可以再這裏找到,我們只是寫好我們的Bean關於bean的初始化、依賴關係、作用域等都是通過Spring配置(這裏特指通過Ioc技術配置)。下面介紹一下Spring3 Ioc容器:Ioc容器相關的兩個主要包org.springframework.context、org.springframework.beans;BeanFactory提供了高級的配置機制來管理所要類型的Bean,同時Spring提供了兩個比較好用的的接口ApplicationContext和WebApplicationContext,看名字就可以知道這兩個類的區別,這兩類都是BeanFactory的子類,他們主要提供了與Spring其他組件和功能的交互,包括Spring AOP 、資源處理(會在後面說明)等。下面通圖2-1來描述下Ioc容器管理相關的類和接口:


圖 2-1

說明:當然Spring的組織不會如此的簡單,這兩主要是爲了說明問題沒有分析所有“Context”類的關係,在E1中我們的測試類中我看使用了ClassPathXmlApplicationContext類來初始化Spring,它通過加載在classpath下定義的配置文件來初始容器,FileSystemApplicationContext支持通過文件系統來加載配置文件。WebApplicationContext是和Web相關的初始化入口。下面是ApplicationContext的一個大致繼承關係圖2-2:


圖 2-2

Spring的核心架構相當簡單 圖2-3摘自Spring3.2文檔:你可以抽象的理解就是使用Spring來組織自己的各種類(事實上Spring做的遠遠不止這些)。


圖 2-3

3:Spring中Bean的配置和屬性:

(下面主要以Annotation配置來說明,Annotation的配置相對寫起程序來說比較簡單但Xml方式提供了更好的擴展性這個在實際引用中要分析來使用,個人認爲一些主要的配置也就是一些入口級的bean在xml中配置比如數據源JMX接入等,細節東西在annotation中配置比較好用比如應用邏輯中自實現的一些bean)。

3.1:Bean相關的一些概念

Scope:

Spring定義了5中Scope類型如圖3-1

圖 3-1

其中request、session、global session只有在web環境下是有效的,這裏先接受前兩個,和web相關的定義在SpringMVC中介紹;

singleton:也就是單例模式的實現,在所用使用singleton Scope定義的bean來說都是是同一個對象;

prototype:也就是原型模式,每一個對使用prototype Scope定義的Bean的引用的Bean所得到的都是一個新的Bean;

e3.2:本小節將以annotation方式介紹一下常用的配置

使用Spring配置的所有Bean我們都可以成爲Component,Spring中@Component註解也就是這麼做的,你可以將自己的Bean註解上@Component然後交給Spring管理,Spring從2.5開始將組件註解有細分了幾類@Repository@Service、 和 @Controller從名字中我們可以看出這是實際上是與MVC的對應,使用上述三個註解的Bean都可以使用@Component來註解,但是上述三個是針對各層次進行優化了的,而且在我們的應用程序中也能更清晰的區分不同業務層的Bean。@Repository從Spring2.0中就引入但還不是對應DAO層的註解,@Service註解是對應我們應用的服務級別類,@Controller註解我們會在SpringMVC中介紹也就是控制層註解。

3.2.1:使用@Component註解示例:類關係如圖3-2(beans.xml配置文件使用e1.2即可)


圖 3-2

IOCTest.java 測試類

package org.fp.smark.spring3;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class IOCTest {
	
	ApplicationContext context  = new ClassPathXmlApplicationContext("beans.xml");
	
	@Test
	public void test1(){
		MainService service = context.getBean("mainService",MainService.class);
		service.hello();
	}
}
測試類通過ClassPathXMLApplication加載配置文件,並調用MainService的hello方法;

MainService.java

package org.fp.smark.spring3;
import javax.annotation.Resource;
import org.springframework.stereotype.Service;

@Service("mainService")  //指定MainService的名字context可以通過這個名字找到這個對象
public class MainService {
	
	@Resource	//使用@Resource註解標明這是一個被注入的資源
	private BasicDao basicDao;
	
	public void hello(){
		System.out.println("hello m Service");
		basicDao.saveEntity();
	}
}

BasicDao.java

package org.fp.smark.spring3;
import org.springframework.stereotype.Component;

@Component("basicDao") //通過@Component進行註解,並指定名字
public class BasicDao {
	
	public void saveEntity(){
		System.out.println("entity saved");
	}
}	

Console輸出:

說明:通過這三個類我們就可以簡單的瞭解Spring Ioc了,下面接收一下使用到的兩個註解;

@Component:這個註解在前面已經簡單的提過了,你可以通過@Component("componectName")來指定這個Bean的名字,這個名字是在使用@Resource定位資源是用到的;當然你也可以不指定,默認是類名第一個字母小寫也就是basicDao。

@Resource:你可以將在類使用的其他對象通過@Resource進行註解這樣Spring會自動幫你創建這個對象,你直接使用就可以了,在上例中我們看到@Resource並沒有傳入參數,默認它是根據定義的對象名也就是basicDao去查找,當指定了名字後他會去按名字查找,@Resource並不僅僅代表容器內資源,你也可以通過@Resource獲取JNDI資源等這裏先不介紹。

@Scope:你可以在類上使用@Scope(BeanDefinition.SCOPE_SINGLETON)註解來使用singleton Scope.

3.2.2:beans.xml配置文件解析

我們以1.2中的beans.xml爲例來看,這個文件簡單的只有一行

<context:component-scan base-package="org.fp.smark.spring3"></context:component-scan>  
來配置,實時上這行配置做了很多工作,從名字我們可以看出其作用就是掃描配置的組件也就是我們自定義的Bean,上面的一行配置隱含的也實現了<context:component-scan>,其對應的是配置了 AutowiredAnnotationBeanPostProcessor和 CommonAnnotationBeanPostProcessor來處理註解,這是我們可以使用註解來進行Spring配置的原因,我們使用註解進行了配置後Spring就能管理我們的各種Bean了。以也可以像下面這樣指定掃描包的過濾規則:
 <context:component-scan base-package="org.example">
      <context:include-filter type="regex" expression=".*Stub.*Repository"/>
      <context:exclude-filter type="annotation"
                              expression="org.springframework.stereotype.Repository"/>
   </context:component-scan>

4、Spring IOC和J2EE CDI

先分析一下概念Inversion of Control(控制反轉IOC)、Dependence Injection(依賴注入DI)雖然兩個概念不同(有些人認爲其實是同一個概念)但是其目的是一致的,個人認爲IOC主要是用戶設計程序時的理解重要的是人理解程序設計中的概念(可能有些模糊),DI是注重藐視程序中類的關係,Spring中的概念是IOC而J2EE中則使用的DI的概念,J2EE從6開始引入DI概念主要是更加JSR 330實現(Dependency Injection for Java 1.0 
),J2EE7中同樣是1.0版本的JSR330實現,Spring中也支持JSR330你可以在Spring中使用@Inject和@Named等註解(個人並不推薦這樣做)如果你有需求可以從Spring文檔中核心技術The Ioc Container中找到相關的說明,個人推薦如果是使用Spring使用Spring自身提供的註解更方便靈活肯定功能也更強大。DI概念引入到J2EE中你可能在其他應用中使用到這個技術來提供類似Spring IOC的效果


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章