一.IOC/DI概念html
參考博客:http://www.javashuo.com/article/p-nnnjsjvx-gk.htmljava
IOC(inversion of control, 控制反轉)是一種設計思想,而不是一種技術. IOC意味着將咱們設計好的對象交給容器控制,而不是交給對象內部控制.它指導咱們設計出鬆耦合,更優良的程序. 傳統程序都是由在類內部主動建立依賴對象來使用, 從而致使類與類之間高耦合, 難於測試; 有了IOC容器,把建立和查找依賴對象的控制權交給了容器, 由容器進行注入組合對象,因此對象和對象之間是鬆耦合, 這樣使得程序的整個體系結構很是靈活.web
實際上,IOC能夠看作是一個大型中介, 將對象的信息登記其中,這個對象是什麼, 這個對象又須要什麼 ,由中介公司給對象分配它須要的資源, 以及將對象分配給須要它的對象.Spring在這個過程當中控制着對象的生命週期和對象間的關係, 全部類的建立和銷燬都由Spring控制, 而不是須要它們的類控制, 這就是控制反轉.spring
DI(Dependency Injection, 依賴注入)是IOC的一個重點,它實現IOC的一種方法,或者說DI是IOC的另外一種說法 , 它負責實現IOC動態地向某個對象提供它所須要的其餘對象. 好比一我的須要一根掃把, 不是由這我的本身去作掃把, 而是由Spring將作好的掃把給他, 而這我的全程須要作的,就是喊我要一根掃把. 什麼叫作依賴, 人須要掃把, 人就對掃把有了依賴. 而DI就是根據這個依賴,將掃把分配給這我的的.session
二.IOC的使用app
參考博客:http://www.javashuo.com/article/p-hksdeorr-by.html函數
IOC實現的兩種方式: XML配置 , Spring註解測試
依賴注入的兩種形式: Setter依賴注入, 構造方法依賴注入 ui
1.XML配置的兩種依賴注入形式:this
(1)Setter依賴注入: 首先建立一個Book類,將其屬性設置好setter,getter方法
public class Book { private int id; private String name; private User user; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public User getUser() { return user; } public void setUser(User user) { this.user = user; } }
而後在applicationContext.xml中添加bean, 告訴Spring二者的依賴關係,實現注入
<bean name="book" class="pojo.Book"> <property name="name" value="book1"></property> <property name="user" ref="user"></property> <!--這裏將book依賴了user,所以在咱們獲取book時,會獲取指定的user對象 --> </bean> <bean name="user" class="pojo.User"> <property name="name" value="user1"></property> <property name="age" value="12"></property> </bean>
(2)構造方法依賴注入:
咱們將BOOK類中添加了一個兩個參數的構造方法,而後在xml文件中肯定兩個參數的值,從而讓spring容器可以創造對象
public class Book { private int id; private String name; private User user; //Constructor public Book(String name,User user){ this.name = name; this.user = user; } }
xml文件中的配置爲: 指定了構造器有兩個參數, 第一個參數是String , 第二個參數指向了另外一個bean
<bean name="book" class="pojo.Book"> <constructor-arg type="java.lang.String"> <!-- 指定參數的類型,能夠在有多個構造器時不產生歧義 --> <value>Adel</value> </constructor-arg> <constructor-arg> <ref bean="user"></ref> </constructor-arg> </bean> <bean name="user" class="pojo.User"> <property name="name" value="user1"></property> <property name="age" value="12"></property> </bean>
或者能夠這樣寫構造參數:
<bean name="book" class="pojo.Book">
<constructor-arg name="name" value="lala"></constructor-arg>
<constructor-arg name="user" ref="user"></constructor-arg>
</bean>
又或者這樣寫:
<bean name="book" class="pojo.Book">
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
(3) Scope對象做用域: 從Spring容器中獲取的對象的做用域能夠修改,默認的做用域爲單例, 具體以下
其在配置中寫在bean的屬性Scope中:
<bean name="book" class="pojo.Book" scope="singleton"> <constructor-arg index="0" value="lala"></constructor-arg> <constructor-arg index="1" ref="user"></constructor-arg> </bean>
(4)延遲初始化bean: 一般ApplicationContext默認在啓動時將全部singleton bean提早實例化. 一般提早實例化是好事,避免某些錯誤由於延遲實例化而不被提早發現. 可是若是想防止提早實例化, 好比你只須要用到book對象, 而不須要它初始化它的user對象, 就能夠用lazy-init屬性來控制
<bean name="book" class="pojo.Book" > <constructor-arg index="0" value="lala"></constructor-arg> <constructor-arg index="1" ref="user"></constructor-arg> </bean> <bean name="user" class="pojo.User" lazy-init="true"> <property name="name" value="user1"></property> <property name="age" value="12"></property> </bean>
(5)回調方法: 初始化回調函數init
public class Book { private int id; private String name; private User user; // Constructor public Book(String name,User user){ this.name = name; this.user = user; } public void init(){ System.out.println("建立了一本書"); } public void destroy(){ System.out.println("銷燬了一本書"); } }
在xml文件中設置初始化回調函數,就會在建立時調用
<bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" >
<constructor-arg index="0" value="lala"></constructor-arg>
<constructor-arg index="1" ref="user"></constructor-arg>
</bean>
2.Spring註解:
註解會削減一些配置的工做量, 可是代碼的耦合度會增長, 應當根據須要使用註解
(1)@Component註解: 這個註解和<bean>做用相似, 經過增長@Component()註解中的參數,指定其在Spring容器中的名稱. 若是不寫,則是默認其在Spring容器中的名稱爲類名的小寫 如User類 在Spring容器中默認名稱爲 user
@Component("user") public class User { private int id; private int age; private String name; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
在配置文件中,即便沒有user這個bean , 其它bean也能夠用到
<bean name="book" class="pojo.Book" init-method="init" destroy-method="destroy" > <constructor-arg index="0" value="lala"></constructor-arg> <constructor-arg index="1" ref="user"></constructor-arg> </bean> <!--<bean name="user" class="pojo.User" lazy-init="true">--> <!--<property name="name" value="user1"></property>--> <!--<property name="age" value="12"></property>--> <!--</bean>-->
(2)@Auotowired 註解: 在Spring中,可使用 @Autowired 註解經過setter方法,構造函數或字段自動裝配Bean。
public class Book { private int id; private String name; private User user; public User getUser() { return user; } @Autowired public void setUser(User user) { this.user = user; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
這樣,即便在applicationContext.xml文件中沒有設置要在book中user依賴哪一個對象, Spring容器也會自動裝配
<bean name="book" class="pojo.Book" > <property name="name" value="lala"></property> <property name="id" value="12"></property> </bean> <bean name="user" class="pojo.User" lazy-init="true"> <property name="name" value="user1"></property> <property name="age" value="12"></property> </bean>
經過構造函數:
public class Book { private int id; private String name; private User user; // Constructor @Autowired public Book(User user){ this.user = user; } }
經過字段:
public class Book { private int id; private String name; @Autowired private User user; }
(3)@Resource註解 : 這個註解與@Autowired不一樣是, 它能夠指定裝配對象的名稱,或者類型,或者二者都指定
如book和user
@Component("u") public class User { private int id; private int age; private String name;
//setter 和 getter
}
@Component("b") public class Book { private int id; private String name; @Resource(name = "u") private User user; //setter和getter }
@Component("b") public class Book { private int id; private String name; @Resource(name = "u",type = User.class) private User user; }
或者這樣
@Component("b") public class Book { private int id; private String name; @Resource(name = "u",type = User.class) private User user;
@Service用於註解業務層組件(咱們一般定義的service層就用這個)
@Controller用於註解控制層組件(如struts中的action)
@Repository用於註解數據訪問組件,即DAO組件
@Component泛指組件,當組件很差歸類的時候,咱們可使用這個註解進行註解。
裝配註解主要有:@Autowired、@Qualifier、@Resource,它們的特色是:
一、@Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean纔會按照類型來裝配注入;
二、@Autowired默認是按照類型裝配注入的,若是想按照名稱來轉配注入,則須要結合@Qualifier一塊兒使用;
三、@Resource註解是由J2EE提供,而@Autowired是由spring提供,故減小系統對spring的依賴建議使用@Resource的方式;若是Maven項目是1.5的JRE則需換成更高版本的。
四、@Resource和@Autowired均可以書寫註解在字段或者該字段的setter方法之上
五、@Autowired 能夠對成員變量、方法以及構造函數進行註釋,而 @Qualifier 的註解對象是成員變量、方法入參、構造函數入參。
六、@Qualifier("XXX") 中的 XX是 Bean 的名稱,因此 @Autowired 和 @Qualifier 結合使用時,自動注入的策略就從 byType 轉變成 byName 了。
七、@Autowired 註釋進行自動注入時,Spring 容器中匹配的候選 Bean 數目必須有且僅有一個,經過屬性required能夠設置非必要。
八、@Resource裝配順序
8.1. 若是同時指定了name和type,則從Spring上下文中找到惟一匹配的bean進行裝配,找不到則拋出異常
8.2. 若是指定了name,則從上下文中查找名稱(id)匹配的bean進行裝配,找不到則拋出異常
8.3. 若是指定了type,則從上下文中找到類型匹配的惟一bean進行裝配,找不到或者找到多個,都會拋出異常
8.4. 若是既沒有指定name,又沒有指定type,則自動按照byName方式進行裝配;若是沒有匹配,則回退爲一個原始類型進行匹配,若是匹配則自動裝配;
如下轉自博客:https://blog.csdn.net/qq_22583741/article/details/79589910
1.@Component取代<bean class="">
@Component("id") 取代 <bean id="" class="">
2.web開發,提供3個@Component註解衍生註解(功能同樣)取代
@Repository :dao層
@Service:service層
@Controller:web層
3.依賴注入,給私有字段設值,也能夠給setter方法設值
普通值:@Value(" ")引用值: 方式1:按照【類型】注入 @Autowired 方式2:按照【名稱】注入1 @Autowired @Qualifier("名稱") 方式3:按照【名稱】注入2 @Resource("名稱") 4.生命週期 初始化:@PostConstruct 銷燬:@PreDestroy 5.做用域 @Scope("prototype") 多例 註解使用前提,添加命名空間,讓spring掃描含有註解類