spring 依賴注入_Spring核心機制:依賴注入
技術標籤:spring 依賴注入spring依賴注入spring依賴注入的三種方式spring呼叫mybatis的dao時是怎樣的
何為依賴關係?
縱觀所有Java應用
,這些應用中大量存在A物件
需要呼叫B物件
方法的情形,這些情形被Spring稱為依賴
,即A物件依賴B物件
,這些相互呼叫的關係稱為依賴關係。
1. 傳統模式下的依賴
當某個Java物件(呼叫者)需要呼叫另一個Java物件(被依賴物件)的方法時,在傳統模式下通常有兩種方法:
1.原始做法:呼叫者主動建立被依賴的物件,然後呼叫被依賴物件的方法。
class Skill { public void run() { System.out.println("我有跑步的能力"); } } class Person { private Skill skill; // 直接在構造器內new一個Skill物件 public Person() { this.skill = new Skill() } public void setSkill(Skill skill) { this.skill = skill; } public void doSports() { skill.run(); //呼叫skill物件的run方法 } }
1.簡單工廠模式:呼叫者先找到被依賴物件的工廠,然後主動通過工廠去獲取被依賴的物件,最後呼叫被依賴物件的方法。
// 定義PersonSkill介面 public interface PersonSkill { void run(); }
class Skill implement PersonSkill { public void run() { System.out.println("我有跑步的能力"); } } // 增加一個工廠類,負責Skill物件的例項化 class PersonSkillFactory { public static PersonSkill getSkill() { return new Skill(); } } class Person { private Skill skill; // 呼叫工廠獲得Skill物件 public Person() { this.skill = PersonSkillFactory.getSkill() } public void doSports() { skill.run(); //呼叫skill物件的run方法 } }
2. Spring核心:依賴注入
對於原始方法,呼叫者通過顯式的new 被依賴物件
建立物件,這將導致呼叫者與被依賴物件的硬編碼耦合。
簡單工廠模式雖然保證了呼叫者與被依賴物件介面的耦合,但仍需要主動通過工廠去獲取被依賴物件,造成呼叫元件與被依賴物件工廠的耦合,並且需要額外的維護一個工廠類,增加了編碼的複雜性。
以上兩種方式都不能很好的實現程式碼的解耦
Spring框架的核心功能有兩個:
•Spring容器作為超級大工廠,負責建立、管理所有的Java物件,這些Java物件被稱為Bean。•Spring管理著Bean之間的依賴關係,這是使用一種稱為“依賴注入”的方式實現的。
Spring引入了xml
Bean
。為了闡述依賴注入的具體含義,針對上面原始做法的示例,我們將Person
與Skill
進行些許改造:
class Skill { public void run() { System.out.println("我有跑步的能力"); }}class Person { private Skill skill; private Integer age; //為skill屬性新增setter方法 public void setSkill(Skill skill) { this.skill = skill; } //為age屬性新增setter方法 public void setAge(Integer age) { this.age = age; } public void doSports() { skill.run(); //呼叫skill物件的run方法 }}
在Resource
目錄下建立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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="person" class="com.codeqis.beans.Person"> <property name="skill" ref="skill"/> <property name="age" value="18"/> bean> <bean id="skill" class="com.codeqis.beans.Skill"/>beans>
完成這些步驟後,意味著將Skill
和Person
這兩個物件的建立權(控制權)交給了Spring,可以理解為將物件的控制權從使用者手中轉移給了由容器控制,這便是控制反轉
。
既然已經把Person的建立交由Spring管理了,那麼我們不應該再手動的new Person()
:
public class App {publicstaticvoidmain(String[]args){ApplicationContextcontext=new ClassPathXmlApplicationContext("spring-beans.xml"); // 方式1Personperson=(Person)context.getBean("person");//傳入beanid // 方式2 Person person2 = context.getBean("person", Person.class); person.doSports(); person1.doSports(); }}
在建立ClassPathXmlApplicationContext
物件時,Spring將在ClassPath
下面尋找spring-beans.xml
,並根據該檔案來建立Spring容器,在此過程中Spring完成所有bean的例項化,併為所有bean注入被依賴的其他bean。
換言之,我們在spring-beans.xml
中聲明瞭id為person
、skill
的兩個bean,Spring容器在建立時自動例項化這兩個類的物件(預設是以單例模式
存在),因為在id為person
的bean下面還存在著子元素,容器在該物件例項化完成後隨即的呼叫該物件的
setSkill
和setAge
方法(由name
指定)完成被依賴物件(由ref指定
)的注入。
正如前面的程式碼中所看到,程式程式碼並沒有主動為Person物件的skill成員變數設定值,而是由Spring容器負責設定,這便是依賴注入。Java EE應用中的各種元件不需要以硬編碼的方式耦合在一起,甚至無需使用工廠模式。個人認為依賴注入達到的效果,非常類似於傳說中的共產主義
,當某個Java例項需要其他Java例項時,系統自動提供所需要的例項,無需顯式獲取。