1. 程式人生 > >Spring依賴注入及使用註解注入bean

Spring依賴注入及使用註解注入bean

Spring 最認同的技術是控制反轉的依賴注入(DI模式。控制反轉(IoC)是一個通用的概念,它可以用許多不同的方式去表達,依賴注入僅僅是控制反轉的一個具體的例子

IOC : Inverse Of Control 控制反轉
      作用:建立物件 並且維護物件之間的依賴關係
DI :依賴注入 Spring支援的注入方式
    構造方法注入
     setter注入
     註解注入

實現原理:反射

IOC:Inversion of Control,控制反轉。指的是物件的建立權反轉(交給)給Spring,其作用是實現了程式的解耦合。也可這樣解釋:獲取物件的方式變了。物件建立的控制權不是“使用者”,而是“框架”或者“容器”。

DIDependency Injection 依賴注入,其實是當一個bean例項引用到了另外一個bean例項時spring容器幫助我們建立依賴bean例項並注入(傳遞)到另一個bean中,如上述案例中的UserServiceImpl類依賴於UserDao的實現類UserDaoImpl,Spring容器會在建立UserService的實現類和UserDao的實現類後,把UserDao的實現類注入UserService例項中,有關依賴注入後面還要詳細講的。

1. 屬性(設值)注入:  〈property〉

     指 IoC 容器通過成員變數的 setter 方法來注入被依賴物件。這種注入方式簡單、直觀,因而在 Spring 依賴注入裡大量使用。

mvc 類

public class User {
	private int id;
	private String username;
	private String password;
	private Map<String,String> map = new HashMap<String,String>();
	private List<String> list = new ArrayList<>(); 	// Set 類同 List

    ... 必須提供 setter 方法
}


public class UserServiceImpl implements UserService{
	//面向介面程式設計
	private UserDao userDao;

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

    ... 必須提供 setter 方法
}

配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="cn.jq.springdemo.model.User">
		<property name="id" value="5"></property>
		<property name="username" value="admin"></property>
                <property name="password" >
			<value><![CDATA[>123<admin><]]></value>
		</property>
		<property name="map">
			<map>
				<entry key="java" value="80"></entry>
				<entry key="spring" value="85"></entry>
			</map>
		</property>
		<property name="list">
			<list>
				<value>lisi</value>
				<value>zs</value>
			</list>
		</property>
	</bean>
	<bean id="userDao" class="cn.jq.springdemo.dao.UserDaoImpl"></bean>

	<bean id="userService"
		class="cn.jq.springdemo.service.UserServiceImpl">
		<property name="userDao" ref="userDao"></property>
	</bean>

</beans>

測試類:

	@Test
	public void test() {
		// 1.初始化ioc容器(裝物件的容器)
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	
		//2.從容器中獲得建立好的物件
		User user = context.getBean("user", User.class);
		System.out.println(user);
	}

-------
User [id=5, username=admin, password=>123<admin><, map={java=80, spring=85}, list=[lisi, zs]]

2. 構造注入:〈constructor-arg〉

    指利用構造器來設定依賴關係的方式。通俗來說,就是驅動Spring在底層以反射方式執行帶指定引數的構造器,當執行帶引數的構造器時,就可利用構造器引數對成員變數執行初始化——這就是構造注入的本質。

mvc 類:

public class UserServiceImpl implements UserService{

	//面向介面程式設計
	private UserDao userDao;
	private User user;
	private int num;
	private String str;

	public UserServiceImpl(UserDao userDao, User user, int num, String str) {
		super();
		this.userDao = userDao;
		this.user = user;
		this.num = num;
		this.str = str;
	}

}

配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="cn.jq.springdemo.model.User">
		<property name="id" value="5"></property>
		<property name="username" value="admin"></property>
	</bean>
	<bean id="userDao" class="cn.jq.springdemo.dao.UserDaoImpl"></bean>

	<bean id="userService"	class="cn.jq.springdemo.service.UserServiceImpl">
		<constructor-arg type="cn.jq.springdemo.dao.UserDao" ref="userDao"></constructor-arg>
		<constructor-arg index="1" ref="user"></constructor-arg>
		<constructor-arg type="int" value="20"></constructor-arg>
		<constructor-arg type="java.lang.String" value="adminstr"></constructor-arg>
	</bean>
</beans>

name - 引數的名字   或者   index - 引數的索引位置 從0開始(注意:構造方法的引數順序)

ref - 指引用型別,指向另外一個bean標籤的id  

vlaue -  指簡單型別的值

測試類:

	@Test
	public void test() {
		// 1.初始化ioc容器(裝物件的容器)
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	
		//2.從容器中獲得建立好的物件
		UserServiceImpl userService = context.getBean("userService",UserServiceImpl.class);
		System.out.println(userService);
	}
-------	
UserServiceImpl [[email protected], user=User [id=5, username=admin, password=null, map={}, list=[]], num=20, str=adminstr]

兩種注入方式的對比

setter注入優點:

  • 與傳統的JavaBean的寫法更相似,程式開發人員更容易理解、接受。通過setter方法設定依賴關係顯得更加直觀、自然。
  • 對於複雜的依賴關係,如果採用構造注入,會導致構造器過於臃腫,難以閱讀。Spring在建立Bean例項時,需要同時例項化其依賴的全部例項,因而導致效能下降。而使用設值注入,則能避免這些問題。
  • 尤其在某些成員變數可選的情況下,多引數的構造器更加笨重。

構造注入優點:

  • 構造注入可以在構造器中決定依賴關係的注入順序,優先依賴的優先注入。
  • 對於依賴關係無需變化的Bean,構造注入更有用處。因為沒有setter方法,所有的依賴關係全部在構造器內設定,無須擔心後續的程式碼對依賴關係產生破壞。
  • 依賴關係只能在構造器中設定,則只有元件的建立者才能改變元件的依賴關係,對元件的呼叫者而言,元件內部的依賴關係完全透明,更符合高內聚的原則。

注意:
建議採用settter注入為主,構造注入為輔的注入策略。對於依賴關係無須變化的注入,儘量採用構造注入;而其他依賴關係的注入,則考慮採用設值注入。

二. Spring的自動裝配(對於大型的應用,不鼓勵使用自動裝配)

Spring自動裝配可通過 <beans/> 元素的 default-autowire 屬性指定,該屬性對配置檔案中所有的Bean起作用;

也可通過對 <bean/> 元素的 autowire 屬性指定,該屬性只對該Bean起作用。

模式 描述
no 這是預設的設定,它意味著沒有自動裝配,你應該使用顯式的bean引用來連線。你不用為了連線做特殊的事。在依賴注入章節你已經看到這個了。
由屬性名自動裝配。Spring 容器看到在 XML 配置檔案中 bean 的自動裝配的屬性設定為 byName。然後嘗試匹配,並且將它的屬性與在配置檔案中被定義為相同名稱的 beans 的屬性進行連線。
由屬性資料型別自動裝配。Spring 容器看到在 XML 配置檔案中 bean 的自動裝配的屬性設定為 byType。然後如果它的型別匹配配置檔案中的一個確切的 bean 名稱,它將嘗試匹配和連線屬性的型別。如果存在不止一個這樣的 bean,則一個致命的異常將會被丟擲。
類似於 byType,但該型別適用於建構函式引數型別。如果在容器中沒有一個建構函式引數型別的 bean,則一個致命錯誤將會發生。
autodetect Spring首先嚐試通過 constructor 使用自動裝配來連線,如果它不執行,Spring 嘗試通過 byType 來自動裝配。

常用兩種模式:

byTpye模式:Spring容器會基於反射檢視bean定義的類,然後找到與依賴型別相同的bean注入到另外的bean中,這個過程需要藉助setter注入來完成,因此必須存在set方法,否則注入失敗。

byName模式:此時Spring只會嘗試將屬性名與bean名稱進行匹配,如果找到則注入依賴bean。

mvc 類

public class UserServiceImpl implements UserService{
	private UserDao userDao; //面向介面程式設計
	private User user;

    ... 必須提供 setter 方法
}

配置檔案:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="user" class="cn.jq.springdemo.model.User">
		<property name="id" value="5"></property>
		<property name="username" value="admin"></property>
		<property name="password" >
			<value><![CDATA[>123<admin><]]></value>
		</property>
	</bean>
	<bean id="userDao" class="cn.jq.springdemo.dao.UserDaoImpl"></bean>

	<!--自動裝配userService類成員屬性
		autowire - byName 自動裝配和成員屬性名稱相同的bean 呼叫的是setter方法注入
						注意:   確保成員屬性的 名稱規範 有對應setter方法 還有就是bean的id和成員屬性的名稱相同
				   byType 根據型別自動裝配
				   		               同一種類型的 bean 只能配置一個唯一的標籤
	 -->
	<bean id="userService"	class="cn.jq.springdemo.service.UserServiceImpl" autowire="byName">
	</bean>
</beans>

測試類:

	@Test
	public void test() {
		// 1.初始化ioc容器(裝物件的容器)
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
	
		//2.從容器中獲得建立好的物件
		UserServiceImpl userService = context.getBean("userService",UserServiceImpl.class);
		System.out.println(userService);
	}
------
UserServiceImpl [[email protected], user=User [id=5, username=admin, password=>123<admin><, map={}, list=[]]]

如果Spring容器中沒有找到可以注入的例項bean時,將不會向依賴屬性值注入任何bean,

這時依賴bean的屬性為 null 或 基本型別預設值。

三. 使用註解注入bean

Spring 使用註解,通過"@XXX"的方式,讓註解與Java Bean緊密結合,既大大減少了配置檔案的體積,又增加了Java Bean的可讀性與內聚性。

首先,在 applicationContext.xml 核心配置檔案中需要用到 context 名稱空間,然後使用 context:component-scan 標籤告訴spring框架,配置了註解的類的位置。

base-package: 指定spring掃描註解的類所在的包(包含子包)。當需要掃描多個包的時候,可以使用逗號分隔。

	
	<!-- 使用註解驅動 自動註冊bean  -->
	<context:component-scan base-package="cn.jq.springdemo"></context:component-scan>

1. 註解說明:

Component最初spring框架設計的,後來為了標識不同程式碼層,衍生出Controller,Service,Repository三個註解 作用相當於配置檔案的bean標籤,被註解的類,spring始化時,就會建立該物件

只能新增在類上  不能新增在抽象類和介面上:

@Controller       用於標註控制層元件,即web業務層。

@Service          用於標註業務層元件,即service層。

@Repository(value="userDao")     用於標註資料訪問元件,即dao層。

@Component    泛指元件,當元件不好歸類的時候,我們可以使用這個註解進行標註。

@Scope(scopeName="singleton")    用於指定scope作用域的(控制類生成的時候採用單例還是多例)

註解屬性 value 對應的是建立的物件的名字 和id相同 (預設配置下預設的名字為 類名首字母小寫)

定義在類的 屬性欄位上:

@Value(value="112")      給簡單型別屬性賦值,可以用在方法上或屬性上

@Resource(name="user")物件引用型別賦值,該值user類必須已經宣告(在配置檔案中已經配置,或在類對應中已經註解)

說一下@Resource 的裝配順序:
(1)、@Resource後面沒有任何內容,預設通過name屬性去匹配bean,找不到再按type去匹配
(2)、指定了name或者type則根據指定的型別去匹配bean
(3)、指定了name和type則根據指定的name和type去匹配bean,任何一個不匹配都將報錯

@Autowired 自動裝配,給物件引用型別賦值,其作用是為了消除程式碼Java程式碼裡面的getter/setter與bean屬性中的property。

    @Autowired(required=false) :Spring容器找不到屬性就丟擲異常,若設定required=false即不再丟擲異常而認為屬性為null

實現類要是有多個,此時可以使用@Qualifier註解來指定你要注入Bean的名稱

    @Autowired
    @Qualifier("student2")

2. @Autowired和@Resource兩個註解的區別:
    1)、@Autowired預設按照byType方式進行bean匹配,@Resource預設按照byName方式進行bean匹配
    2)、@Autowired是Spring的註解,@Resource是J2EE的註解,

3. Spring常用註解彙總

@Configuration把一個類作為一個IoC容器,它的某個方法頭上如果註冊了@Bean,就會作為這個Spring容器中的Bean。
@Scope註解 作用域
@Lazy(true) 表示延遲初始化
@Service用於標註業務層元件、 
@Controller用於標註控制層元件(如struts中的action)
@Repository用於標註資料訪問元件,即DAO元件。
@Component泛指元件,當元件不好歸類的時候,我們可以使用這個註解進行標註。
@Scope用於指定scope作用域的(用在類上

@PostConstruct用於指定初始化方法(用在方法上)
@PreDestory用於指定銷燬方法(用在方法上)
@DependsOn:定義Bean初始化及銷燬時的順序
@Primary:自動裝配時當出現多個Bean候選者時,被註解為@Primary的Bean將作為首選者,否則將丟擲異常
@Autowired 預設按型別裝配,如果我們想使用按名稱裝配,可以結合@Qualifier註解一起使用。如下:
@Autowired @Qualifier("personDaoBean") 存在多個例項配合使用
@Resource預設按名稱裝配,當找不到與名稱匹配的bean才會按型別裝配。

@PostConstruct 初始化註解
@PreDestroy 摧毀註解 預設 單例  啟動就載入
@Async非同步方法呼叫

四、泛型依賴注入(spring 4.x以上版本才有

泛型依賴注入就是允許我們在使用spring進行依賴注入的同時,利用泛型的優點對程式碼進行精簡,將可重複使用的程式碼全部放到一個類之中,方便以後的維護和修改。同時在不增加程式碼的情況下增加程式碼的複用性。

BaseDao<T> 類: 泛型方法引數控制

BaseService<T>   類: 物件引用屬性 baseDao控制,泛型注入 

相關推薦

Spring注入:配置注入(set注入和構造器注入)與註解注入

轉自:http://blog.csdn.net/u011579138/article/details/51379066 注入簡介 Spring注入可以理解為是對一個物件進行初始化,也就是省去new的這個步驟,類似於工廠模式一樣,通過一個工廠製造出這個物件,如果遇到修

Spring的類屬性註解注入

一.配置applicationContext.xml <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"

7、SSM框架-Spring之IOC的註解注入(7)

用註解來向Spring容器註冊Bean。需要在applicationContext.xml中註冊<context:component-scan base-package=”pagkage1[,pagkage2,…,pagkageN]”/>。 如:在base-pa

(轉)java之Spring(IOC)註解裝配Bean詳解

pos work 多個 public pre tor not 註解裝配 creat 在這裏我們要詳細說明一下利用Annotation-註解來裝配Bean。 因為如果你學會了註解,你就再也不願意去手動配置xml文件了,下面就看看Annotation的魅力所在吧。 先

Spring三】使用註解配置bean

原理:      1、當啟動spring容器的時候,給spring容器的bean建立物件      2、當spring容器解析到<context:annotation-config></context:annotation-config>的時候,          spring容器掃描

SQL注入防止注入措施

1、Sql注入是怎麼產生的? WEB開發人員無法保證所有的輸入都已經過濾 攻擊者利用傳送給SQL伺服器的輸入資料構造可執行的SQL程式碼 資料庫未做相應的安全配置 2、如何尋找Sql注入? 識別web應用中的所有輸入點 瞭解哪些型別的請求會出發異

Spring Boot配置註解詳解

一般情況下,我們建立了一個Spring Boot程式之後,按照預設的配置就可以啟動了,但是我們還是可以自定義一些配置以及修改一些配置一:多個環境的檔案配置由於一個專案在開發的過程當中,需要經歷開發測試以及正式部署三個階段,我們可以根據不同的環境作不同的配置,配置的格式嚴格遵循

Spring依賴注入使用註解注入bean

Spring 最認同的技術是控制反轉的依賴注入(DI)模式。控制反轉(IoC)是一個通用的概念,它可以用許多不同的方式去表達,依賴注入僅僅是控制反轉的一個具體的例子。 IOC : Inverse Of Control 控制反轉       作用:建立物件 並且維護物件之間的

Spring 使用註解完成bean例項化、依賴注入的相關配置以及注意事項

一、 相關配置例項化註解介紹 首先使用註解完成spring容器例項的配置,主要用到以下幾個: 1、@Repository(“name”):配置持久層例項bean,通常用在DAO; 這裡配置的name屬性相當於在 2、@Servic

Spring 註解實現Bean依賴注入之@Qualifier

三、@Qualifier:限定描述符,用於細粒度選擇候選者; @Autowired預設是根據型別進行注入的,因此如果有多個型別一樣的Bean候選者,則需要限定其中一個候選者,否則將丟擲異常 @Qualifier限定描述符除了能根據名字進行注入,更能進行更細粒度的控制如何選擇

Spring 註解實現Bean依賴注入之@Required

對應於基於XML配置中的依賴檢查,但XML配置的依賴檢查將檢查所有setter方法; 基於@Required的依賴檢查表示註解的setter方法必須,即必須通過在XML配置中配置setter注入,如果沒有配置,在容器啟動時會丟擲異常,從而保證在執行時不會遇到空指標異常,@Required只能放置在set

Spring註解注入bean和配置檔案注入bean

註解的方式確實比手動寫xml檔案注入要方便快捷很多,省去了很多不必要的時間去寫xml檔案 按以往要注入bean的時候,需要去配置一個xml,當然也可以直接掃描包體,用xml注入bean有以下方法: 1 <?xml version="1.0" encoding="UTF-8"?> 2

spring 使用註解注入bean

學了兩種使用註解注入bean的方式,按照網上提供的方法學習並整理的。 1、@Resource  2、@Autowired 首先要說明的是 spring的標頭檔案,下面是一個比較全的標頭檔案 <beans xmlns="http://www.springfram

Spring依賴注入(構造引數注入、集合,陣列屬性注入、XML自動注入 ,全註解配置)

依賴注入 構造引數注入        --> 常用的是方案一和方案二         MyBean類  YouBean類 <?xml version="1.0" encodin

spring依賴注入 -------基於註解方式

前言: 做了2年的軟體,剛開始入行的時候,沒有個目標基本上都是在摸索,技術看的我眼花繚亂,這個想學,那個也想學結果是對很多技術一知半解的,工作中才發現,我們要掌握的一門可以搞定快速開發搞定所有業務需求的技術, 所以現在我要對spring的東西達到一個深層次的掌握,儘量避免百度,在開發

spring boot去除掃描自動注入依賴方法——Spring常用註解使用方法

問題: 最近做專案的時候,需要引入其他的jar。然後還需要掃描這些jar裡的某些bean。於 是使用註解:@ComponentScan 這個註解直接指定包名就可以,它會去掃描這個包下所有的class,然後判斷是否解析: 原始碼: public @interface SpringBoo

spring依賴注入: 註解注入

註解注入顧名思義就是通過註解來實現注入, Spring和注入相關的常見註解有Autowired、Resource、Qualifier、Service、Controller、Repository、Component。 [email protected]是自動注入

Spring 在靜態工具類中使用註解注入bean

問題 最近在專案中遇到這樣一個情況:有一個傳送郵件的工具類。在這個工具類中提供了幾種靜態方法,靜態方法需要另外一個類的例項提供處理。在static方法裡呼叫注入進來的service,因為是靜態方法,所以必須宣告該service也必須是static的,這時候發現

spring 框架中的依賴注入(IOC--設值注入)--使用註解--的具體例項的簡單實現

體現了具體專案工程裡面的分層,dao,daoImpl,service,serviceImpl,action。讓你真正的理解這為啥分層。 順便清清楚楚的理解@Component、@Service、@Re

spring 在單例類中使用註解注入bean

/** * @author: jerry * @Email: * @Company: * @Action: 日誌處理工具類 * @DATE: 2016-9-19 */ @Component//泛指元件,當元件不好歸類的時候,我們可以使用這個註解進行標註 p