當前位置:首頁 » 操作系統 » spring依賴注入源碼

spring依賴注入源碼

發布時間: 2022-06-10 01:39:34

『壹』 如何使用spring實現依賴注入

Spring通過一種稱作控制反轉(IoC)的技術促進了松耦合。當應用了IoC,一個對象依賴的其它對象會通過被動的方式傳遞進來,而不是這個對象自己創建或者查找依賴對象。 你可以認為IoC與JNDI相反——不是對象從容器中查找依賴,而是容器在對象初始化

『貳』 spring依賴注入有幾種方式

這是最簡單的注入方式,假設有一個SpringAction,類中需要實例化一個SpringDao對象,那麼就可以定義一個private的SpringDao成員變數,然後創建SpringDao的set方法(這是ioc的注入入口):
java代碼
package com.bless.springdemo.action;
public class SpringAction {
//注入對象springDao
private SpringDao springDao;
//一定要寫被注入對象的set方法
public void setSpringDao(SpringDao springDao) {
this.springDao = springDao;
}

『叄』 spring依賴注入,和控制反轉。用自己的話說是怎麼說的。最好能夠用代碼來解釋

spring的依賴注入(DI)和控制反轉(IOC)其實是一個概念。簡單的說就是「你不用來找我,我會去找你」。就是我們在用對象的初始化是在我們用對象的時候有系統自動初始化,而不是我們顯式的去做這項工作。依賴注入的方法有三種,其中最常用的是setter方法注入。給你舉個例子吧。
假設有一個介面A和它的實現Aimpl。我們在B類中需要用到Aimpl。在IOC之前情況下我們會這么寫
B{
A a=new Aimpl();
//其他代碼
}
現在,有了IOC之後只需要
B{
A a;

//其他代碼
public void setA(A a) {
this.a = a;
}
}
當然要在spring的配置文檔applicationContext中配置A的bean
相關資料可以參考下spring的書

『肆』 spring實現控制反轉與依賴注入

IoC與DI
首先想說說IoC(Inversion of Control,控制倒轉)。這是spring的核心,貫穿始終。所謂IoC,對於spring框架來說,就是由spring來負責控制對象的生命周期和對象間的關系。這是什麼意思呢,舉個簡單的例子,我們是如何找女朋友的?常見的情況是,我們到處去看哪裡有長得漂亮身材又好的mm,然後打聽她們的興趣愛好、qq號、電話號、ip號、iq號………,想辦法認識她們,投其所好送其所要,然後嘿嘿……這個過程是復雜深奧的,我們必須自己設計和面對每個環節。傳統的程序開發也是如此,在一個對象中,如果要使用另外的對象,就必須得到它(自己new一個,或者從JNDI中查詢一個),使用完之後還要將對象銷毀(比如Connection等),對象始終會和其他的介面或類藕合起來。
那麼IoC是如何做的呢?有點像通過婚介找女朋友,在我和女朋友之間引入了一個第三者:婚姻介紹所。婚介管理了很多男男女女的資料,我可以向婚介提出一個列表,告訴它我想找個什麼樣的女朋友,比如長得像李嘉欣,身材像林熙雷,唱歌像周傑倫,速度像卡洛斯,技術像齊達內之類的,然後婚介就會按照我們的要求,提供一個mm,我們只需要去和她談戀愛、結婚就行了。簡單明了,如果婚介給我們的人選不符合要求,我們就會拋出異常。整個過程不再由我自己控制,而是有婚介這樣一個類似容器的機構來控制。Spring所倡導的開發方式就是如此,所有的類都會在spring容器中登記,告訴spring你是個什麼東西,你需要什麼東西,然後spring會在系統運行到適當的時候,把你要的東西主動給你,同時也把你交給其他需要你的東西。所有的類的創建、銷毀都由 spring來控制,也就是說控制對象生存周期的不再是引用它的對象,而是spring。對於某個具體的對象而言,以前是它控制其他對象,現在是所有對象都被spring控制,所以這叫控制反轉。如果你還不明白的話,我決定放棄。
IoC的一個重點是在系統運行中,動態的向某個對象提供它所需要的其他對象。這一點是通過DI(Dependency Injection,依賴注入)來實現的。比如對象A需要操作資料庫,以前我們總是要在A中自己編寫代碼來獲得一個Connection對象,有了 spring我們就只需要告訴spring,A中需要一個Connection,至於這個Connection怎麼構造,何時構造,A不需要知道。在系統運行時,spring會在適當的時候製造一個Connection,然後像打針一樣,注射到A當中,這樣就完成了對各個對象之間關系的控制。A需要依賴 Connection才能正常運行,而這個Connection是由spring注入到A中的,依賴注入的名字就這么來的。那麼DI是如何實現的呢? Java 1.3之後一個重要特徵是反射(reflection),它允許程序在運行的時候動態的生成對象、執行對象的方法、改變對象的屬性,spring就是通過反射來實現注入的。關於反射的相關資料請查閱java doc。
理解了IoC和DI的概念後,一切都將變得簡單明了,剩下的工作只是在spring的框架中堆積木而已。

如果還不明白,放棄java吧!

下面來讓大家了解一下Spring到底是怎麼運行的。

Java代碼

public static void main(String[] args) {
ApplicationContext context = new (
"applicationContext.xml");
Animal animal = (Animal) context.getBean("animal");
animal.say();
}

public static void main(String[] args) {
ApplicationContext context = new (
"applicationContext.xml");
Animal animal = (Animal) context.getBean("animal");
animal.say();
}

這段代碼你一定很熟悉吧,不過還是讓我們分析一下它吧,首先是applicationContext.xml

Java代碼

<bean id="animal" class="phz.springframework.test.Cat">
<property name="name" value="kitty" />
</bean>

<bean id="animal" class="phz.springframework.test.Cat">
<property name="name" value="kitty" />
</bean>

他有一個類phz.springframework.test.Cat

Java代碼

public class Cat implements Animal {
private String name;
public void say() {
System.out.println("I am " + name + "!");
}
public void setName(String name) {
this.name = name;
}
}

public class Cat implements Animal {
private String name;
public void say() {
System.out.println("I am " + name + "!");
}
public void setName(String name) {
this.name = name;
}
}

實現了phz.springframework.test.Animal介面

Java代碼

public interface Animal {
public void say();
}

public interface Animal {
public void say();
}

很明顯上面的代碼輸出I am kitty!

那麼到底Spring是如何做到的呢?
接下來就讓我們自己寫個Spring 來看看Spring 到底是怎麼運行的吧!

首先,我們定義一個Bean類,這個類用來存放一個Bean擁有的屬性

Java代碼

/* Bean Id */
private String id;
/* Bean Class */
private String type;
/* Bean Property */
private Map<String, Object> properties = new HashMap<String, Object>();

/* Bean Id */
private String id;
/* Bean Class */
private String type;
/* Bean Property */
private Map<String, Object> properties = new HashMap<String, Object>();

一個Bean包括id,type,和Properties。

接下來Spring 就開始載入我們的配置文件了,將我們配置的信息保存在一個HashMap中,HashMap的key就是Bean 的 Id ,HasMap 的value是這個Bean,只有這樣我們才能通過context.getBean("animal")這個方法獲得Animal這個類。我們都知道 Spirng可以注入基本類型,而且可以注入像List,Map這樣的類型,接下來就讓我們以Map為例看看Spring是怎麼保存的吧

Map配置可以像下面的

Java代碼

<bean id="test" class="Test">
<property name="testMap">
<map>
<entry key="a">
<value>1</value>
</entry>
<entry key="b">
<value>2</value>
</entry>
</map>
</property>
</bean>

<bean id="test" class="Test">
<property name="testMap">
<map>
<entry key="a">
<value>1</value>
</entry>
<entry key="b">
<value>2</value>
</entry>
</map>
</property>
</bean>

Spring是怎樣保存上面的配置呢?,代碼如下:

Java代碼

if (beanProperty.element("map") != null) {
Map<String, Object> propertiesMap = new HashMap<String, Object>();
Element propertiesListMap = (Element) beanProperty
.elements().get(0);
Iterator<?> propertiesIterator = propertiesListMap
.elements().iterator();
while (propertiesIterator.hasNext()) {
Element vet = (Element) propertiesIterator.next();
if (vet.getName().equals("entry")) {
String key = vet.attributeValue("key");
Iterator<?> valuesIterator = vet.elements()
.iterator();
while (valuesIterator.hasNext()) {
Element value = (Element) valuesIterator.next();
if (value.getName().equals("value")) {
propertiesMap.put(key, value.getText());
}
if (value.getName().equals("ref")) {
propertiesMap.put(key, new String[] { value
.attributeValue("bean") });
}
}
}
}
bean.getProperties().put(name, propertiesMap);
}

if (beanProperty.element("map") != null) {
Map<String, Object> propertiesMap = new HashMap<String, Object>();
Element propertiesListMap = (Element) beanProperty
.elements().get(0);
Iterator<?> propertiesIterator = propertiesListMap
.elements().iterator();
while (propertiesIterator.hasNext()) {
Element vet = (Element) propertiesIterator.next();
if (vet.getName().equals("entry")) {
String key = vet.attributeValue("key");
Iterator<?> valuesIterator = vet.elements()
.iterator();
while (valuesIterator.hasNext()) {
Element value = (Element) valuesIterator.next();
if (value.getName().equals("value")) {
propertiesMap.put(key, value.getText());
}
if (value.getName().equals("ref")) {
propertiesMap.put(key, new String[] { value
.attributeValue("bean") });
}
}
}
}
bean.getProperties().put(name, propertiesMap);
}

接下來就進入最核心部分了,讓我們看看Spring 到底是怎麼依賴注入的吧,其實依賴注入的思想也很簡單,它是通過反射機制實現的,在實例化一個類時,它通過反射調用類中set方法將事先保存在HashMap中的類屬性注入到類中。讓我們看看具體它是怎麼做的吧。
首先實例化一個類,像這樣

Java代碼

public static Object newInstance(String className) {
Class<?> cls = null;
Object obj = null;
try {
cls = Class.forName(className);
obj = cls.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return obj;
}

public static Object newInstance(String className) {
Class<?> cls = null;
Object obj = null;
try {
cls = Class.forName(className);
obj = cls.newInstance();
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
return obj;
}

接著它將這個類的依賴注入進去,像這樣

Java代碼

public static void setProperty(Object obj, String name, String value) {
Class<? extends Object> clazz = obj.getClass();
try {
String methodName = returnSetMthodName(name);
Method[] ms = clazz.getMethods();
for (Method m : ms) {
if (m.getName().equals(methodName)) {
if (m.getParameterTypes().length == 1) {
Class<?> clazzParameterType = m.getParameterTypes()[0];
setFieldValue(clazzParameterType.getName(), value, m,
obj);
break;
}
}
}
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}

public static void setProperty(Object obj, String name, String value) {
Class<? extends Object> clazz = obj.getClass();
try {
String methodName = returnSetMthodName(name);
Method[] ms = clazz.getMethods();
for (Method m : ms) {
if (m.getName().equals(methodName)) {
if (m.getParameterTypes().length == 1) {
Class<?> clazzParameterType = m.getParameterTypes()[0];
setFieldValue(clazzParameterType.getName(), value, m,
obj);
break;
}
}
}
} catch (SecurityException e) {
throw new RuntimeException(e);
} catch (IllegalArgumentException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
}
}

最後它將這個類的實例返回給我們,我們就可以用了。我們還是以Map為例看看它是怎麼做的,我寫的代碼裡面是創建一個HashMap並把該HashMap注入到需要注入的類中,像這樣,

Java代碼

if (value instanceof Map) {
Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()
.iterator();
Map<String, Object> map = new HashMap<String, Object>();
while (entryIterator.hasNext()) {
Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();
if (entryMap.getValue() instanceof String[]) {
map.put((String) entryMap.getKey(),
getBean(((String[]) entryMap.getValue())[0]));
}
}
BeanProcesser.setProperty(obj, property, map);
}

if (value instanceof Map) {
Iterator<?> entryIterator = ((Map<?, ?>) value).entrySet()
.iterator();
Map<String, Object> map = new HashMap<String, Object>();
while (entryIterator.hasNext()) {
Entry<?, ?> entryMap = (Entry<?, ?>) entryIterator.next();
if (entryMap.getValue() instanceof String[]) {
map.put((String) entryMap.getKey(),
getBean(((String[]) entryMap.getValue())[0]));
}
}
BeanProcesser.setProperty(obj, property, map);
}

好了,這樣我們就可以用Spring 給我們創建的類了,是不是也不是很難啊?當然Spring能做到的遠不止這些,這個示常式序僅僅提供了Spring最核心的依賴注入功能中的一部分。

具體配置可以看下面鏈接:
http://zhaohe162.blog.163.com/blog/static/3821679720105711512570/

<!-- 配置數據持久層 -->
<bean id="userDao"
class="com.ssh..impl.UserDaoImpl">
<property name="hibernateTemplate" ref="hibernateTemplate"></property>
</bean>

<!-- 配置業務邏輯層 -->
<bean id="userService"
class="com.ssh.service.impl.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>

<!-- 配置控制層 -->
<bean id="UserAction"
class="com.ssh.action.UserAction" scope="prototype">
<property name="userService" ref="userService"></property>
</bean>
<!-- 配置pojo -->
<bean id="User" class="com.ssh.pojo.User" scope="prototype"/>
</beans>

『伍』 spring的依賴注入和控制反轉

IoC,依賴注入也稱控制反轉。傳統的被調用者是由代碼來創建調用的,而spring改變了這種傳統的思想。當類創建的時候,spring容器就把被調用者注入到類中。控制權從主動改為被動接受。這就是我對Ioc的理解。

『陸』 如何查看spring源碼

1.准備工作:在官網上下載了Spring源代碼之後,導入Eclipse,以方便查詢。
2.打開我們使用Spring的項目工程,找到Web.xml這個網站系統配置文件,在其中找到Spring的初始化信息:

<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

由配置信息可知,我們開始的入口就這里ContextLoaderListener這個監聽器。
在源代碼中我們找到了這個類,它的定義是:
public class ContextLoaderListener extends ContextLoader
implements ServletContextListener {

/**
* Initialize the root web application context.
*/
public void contextInitialized(ServletContextEvent event) {
this.contextLoader = createContextLoader();
if (this.contextLoader == null) {
this.contextLoader = this;
}
this.contextLoader.initWebApplicationContext(event.getServletContext());
}
...
}

該類繼續了ContextLoader並實現了監聽器,關於Spring的信息載入配置、初始化便是從這里開始了,具體其他閱讀另外寫文章來深入了解。
二、關於IOC和AOP
關於Spring IOC 網上很多相關的文章可以閱讀,那麼我們從中了解到的知識點是什麼?
1)IOC容器和AOP切面依賴注入是Spring是核心。
IOC容器為開發者管理對象之間的依賴關系提供了便利和基礎服務,其中Bean工廠(BeanFactory)和上下文(ApplicationContext)就是IOC的表現形式。BeanFactory是個介面類,只是對容器提供的最基本服務提供了定義,而DefaultListTableBeanFactory、XmlBeanFactory、ApplicationContext等都是具體的實現。
介面:

public interface BeanFactory {
//這里是對工廠Bean的轉義定義,因為如果使用bean的名字檢索IOC容器得到的對象是工廠Bean生成的對象,
//如果需要得到工廠Bean本身,需要使用轉義的名字來向IOC容器檢索
String FACTORY_BEAN_PREFIX = "&";
//這里根據bean的名字,在IOC容器中得到bean實例,這個IOC容器就象一個大的抽象工廠,用戶可以根據名字得到需要的bean
//在Spring中,Bean和普通的JAVA對象不同在於:
//Bean已經包含了我們在Bean定義信息中的依賴關系的處理,同時Bean是已經被放到IOC容器中進行管理了,有它自己的生命周期
Object getBean(String name) throws BeansException;
//這里根據bean的名字和Class類型來得到bean實例,和上面的方法不同在於它會拋出異常:如果根名字取得的bean實例的Class類型和需要的不同的話。
Object getBean(String name, Class requiredType) throws BeansException;
//這里提供對bean的檢索,看看是否在IOC容器有這個名字的bean
boolean containsBean(String name);
//這里根據bean名字得到bean實例,並同時判斷這個bean是不是單件,在配置的時候,默認的Bean被配置成單件形式,如果不需要單件形式,需要用戶在Bean定義信息中標注出來,這樣IOC容器在每次接受到用戶的getBean要求的時候,會生成一個新的Bean返回給客戶使用 - 這就是Prototype形式
boolean isSingleton(String name) throws NoSuchBeanDefinitionException;
//這里對得到bean實例的Class類型
Class getType(String name) throws NoSuchBeanDefinitionException;
//這里得到bean的別名,如果根據別名檢索,那麼其原名也會被檢索出來
String[] getAliases(String name);
}

實現:
XmlBeanFactory的實現是這樣的:
public class XmlBeanFactory extends DefaultListableBeanFactory {
//這里為容器定義了一個默認使用的bean定義讀取器,在Spring的使用中,Bean定義信息的讀取是容器初始化的一部分,但是在實現上是和容器的注冊以及依賴的注入是分開的,這樣可以使用靈活的 bean定義讀取機制。
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
//這里需要一個Resource類型的Bean定義信息,實際上的定位過程是由Resource的構建過程來完成的。
public XmlBeanFactory(Resource resource) throws BeansException {
this(resource, null);
}
//在初始化函數中使用讀取器來對資源進行讀取,得到bean定義信息。這里完成整個IOC容器對Bean定義信息的載入和注冊過程
public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws
BeansException {
super(parentBeanFactory);
this.reader.loadBeanDefinitions(resource);
}

『柒』 在spring中可以通過什麼實現依賴注入

依賴注入:本質就是對類中的變數進行賦值操作!
spring 使用註解標注類,spring容器通過包掃描註解,將這些標注了spring註解的類管理起來。
1、@service註解:
標注在一個service層的業務類上,告訴spring容器這是一個service層業務類,spring就會自動創建這個類的實例,在你需要這個對象的地方將它注入。
標注了這個註解的類在spring容器中生成的對象的id默認是首字母小寫的類名,也可以由自己指定@service("name")
2、@Reposity註解:
標注在層的類或介面上,告訴spring容器這是一個層的類或介面,spring容器自動創建這個類的實例並且管理起來。默認id是類名或介面名首字母小寫,可自己指定。
3、@Component註解:
萬能註解,它可以標注在你寫的任意類上,在類上標注了這個註解,就會將這個類交由spring容器來進行管理,包括創建實例和依賴注入。

『捌』 Spring 的依賴注入是什麼意思

依賴注入(Dependency Injection)和控制反轉(Inversion of Control)是同一個概念。具體含義是:當某個角色(可能是一個Java實例,調用者)需要另一個角色(另一個Java實例,被調用者)的協助時,在 傳統的程序設計過程中,通常由調用者來創建被調用者的實例。但在Spring里,創建被調用者的工作不再由調用者來完成,因此稱為控制反轉;創建被調用者 實例的工作通常由Spring容器來完成,然後注入調用者,因此也稱為依賴注入。

『玖』 spring的依賴注入能不能通俗易懂的給我講解下 有點迷糊...

spring的依賴注入有兩種:一種是屬性的注入,另一種是構造方法的注入。一般常用的是屬性的注入,即假設現在有個UserBiz要調用UserDao層進行數據的增刪改查。那麼以前的作法是:
class UserBiz{
//new一個對象
UserDao userDao = new UserDao();
//調用對象的方法
...........
}

那麼,以後進行二次開發的時候,我們加入更改了UserDao的方法那麼所有調用這個對象的類都需要改動,增加後期的維護成本。所以,Spring中有了IOC的概念,即:將原來代碼的控制權移到配置文件中。這樣代碼的改動就很小,只要更改配置文件即可。
具體的可以搜索下相關spring的框架只是,最好看源碼

『拾』 spring中依賴注入的原理

  1. Spring從核心而言,是一個DI容器,其設計哲學是提供一種無侵入式的高擴展性框架。即無需代碼中涉及Spring專有類,即可將其納入Spring容器進行管理。

  2. 作為對比,EJB則是一種高度侵入性的框架規范,它制定了眾多的介面和編碼規范,要求實現者必須 遵從。侵入性的後果就是,一旦系統基於侵入性框架設計開發,那麼之後任何脫離這個框架的企圖都將付 出極大的代價。

  3. 為了避免這種情況,實現無侵入性的目標。Spring大量引入了Java的Reflection機制,通過動態 調用的方式避免硬編碼方式的約束,並在此基礎上建立了其核心組件BeanFactory,以此作為其依賴注入機制的實現基礎。

  4. org.springframework.beans包中包括了這些核心組件的實現類,核心中的核心為BeanWrapper 和BeanFactory類。這兩個類從技術角度而言並不復雜,但對於Spring框架而言,卻是關鍵所在。

  5. InputStreamis=newFileInputStream("bean.xml"); XmlBeanFactoryfactory=newXmlBeanFactory(is); Actionaction=(Action)factory.getBean("TheAction");

  6. 此時獲得的Action實例,由BeanFactory進行載入,並根據配置文件進行了初始化和屬性設定。

  7. 聯合上面關於BeanWrapper的內容,可以看到,BeanWrapper實現了針對單個Bean的屬性設 定操作。而BeanFactory則是針對多個Bean的管理容器,根據給定的配置文件,BeanFactory從中讀取 類名、屬性名/值,然後通過Reflection機制進行Bean載入和屬性設定。

熱點內容
centos升級python27 發布:2024-11-02 02:00:57 瀏覽:673
ue4未找到編譯器 發布:2024-11-02 01:46:08 瀏覽:155
python中的withopen 發布:2024-11-02 01:46:07 瀏覽:976
編程名人 發布:2024-11-02 01:42:18 瀏覽:867
伺服器電腦配置表 發布:2024-11-02 01:41:29 瀏覽:370
linux使用串口 發布:2024-11-02 01:37:11 瀏覽:702
二維碼掃的密碼從哪裡開始 發布:2024-11-02 01:24:57 瀏覽:473
如何將手錶改成開放式安卓系統 發布:2024-11-02 01:09:00 瀏覽:739
6s還能用嗎能和什麼安卓機比 發布:2024-11-02 01:08:09 瀏覽:765
SQL擴位 發布:2024-11-02 00:55:35 瀏覽:447