IOC理論
在一開(kāi)始學(xué)習(xí) Spring 的時(shí)候,我們就接觸 IOC 了,作為 Spring 第一個(gè)最核心的概念,我們?cè)诮庾x它之前一定需要對(duì)其有深入的認(rèn)識(shí)。
IoC 全稱(chēng)為 InversionofControl,翻譯為 “”,它還有一個(gè)別名為 DI( DependencyInjection),即依賴(lài)注入。
如何理解“控制反轉(zhuǎn)”好呢?理解好它的關(guān)鍵在于我們需要回答如下四個(gè)問(wèn)題:
誰(shuí)控制誰(shuí)
控制什么
為何是反轉(zhuǎn)
哪些方面反轉(zhuǎn)了
分析實(shí)現(xiàn)
1.先寫(xiě)一個(gè)UserDao接口
?public interface UserDao {
? ? public void getUser();
? }
2.再去寫(xiě)Dao的實(shí)現(xiàn)類(lèi)
?public class UserDaoImpl implements UserDao {
? ? @Override
? ? public void getUser() {
? ? ? System.out.println("獲取用戶(hù)數(shù)據(jù)");
? ? }
? }
3.然后去寫(xiě)UserService的接口
?public interface UserService {
? ? public void getUser();
? }
4.最后寫(xiě)Service的實(shí)現(xiàn)類(lèi)
?public class UserServiceImpl implements UserService {
? ? private UserDao userDao = new UserDaoImpl();
?
? ? @Override
? ? public void getUser() {
? ? ? userDao.getUser();
? ? }
? }
5.測(cè)試一下
? @Test
? public void test(){
? ? UserService service = new UserServiceImpl();
? ? service.getUser();
? }
這是最原始的方法,現(xiàn)在來(lái)修改一下
把UserDao的實(shí)現(xiàn)類(lèi)增加一個(gè)
?public class UserDaoMySqlImpl implements UserDao {
? ? @Override
? ? public void getUser() {
? ? ? System.out.println("MySql獲取用戶(hù)數(shù)據(jù)");
? ? }
? }
接下來(lái)我們要實(shí)現(xiàn)MySQL就要去service實(shí)現(xiàn)類(lèi)里修改對(duì)應(yīng)的實(shí)現(xiàn)
?public class UserServiceImpl implements UserService {
? ? private UserDao userDao = new UserDaoMySqlImpl();
?
? ? @Override
? ? public void getUser() {
? ? ? userDao.getUser();
? ? }
? }
如果我們?cè)僭黾右粋€(gè)userdao的實(shí)現(xiàn)類(lèi)
?public class UserDaoOracleImpl implements UserDao {
? ? @Override
? ? public void getUser() {
? ? ? System.out.println("Oracle獲取用戶(hù)數(shù)據(jù)");
? ? }
? }
那么我們要使用Oracle , 又需要去service實(shí)現(xiàn)類(lèi)里面修改對(duì)應(yīng)的實(shí)現(xiàn) . 假設(shè)我們的這種需求非常大 , 這種方式就根本不適用了, 甚至反人類(lèi)對(duì)吧 , 每次變動(dòng) , 都需要修改大量代碼 . 這種設(shè)計(jì)的耦合性太高了, 牽一發(fā)而動(dòng)全身 .
如何解決這個(gè)問(wèn)題呢
我們可以在需要用到他的地方 , 不去實(shí)現(xiàn)它 , 而是留出一個(gè)接口 , 利用set , 我們?nèi)ゴa里修改下 .
?public class UserServiceImpl implements UserService {
? ? ?private UserDao userDao;
? ? ?// 利用set實(shí)現(xiàn)
? ? public void setUserDao(UserDao userDao) {
? ? ? this.userDao = userDao;
? ? }
? ?
? ? ?@Override
? ? ?public void getUser() {
? ? ? userDao.getUser();
? ? }
? }
現(xiàn)在去我們的測(cè)試類(lèi)里 , 進(jìn)行測(cè)試
?@Test
? public void test(){
? ? UserServiceImpl service = new UserServiceImpl();
? ? service.setUserDao( new UserDaoMySqlImpl() );
? ? service.getUser();
? ? //那我們現(xiàn)在又想用Oracle去實(shí)現(xiàn)呢
? ? service.setUserDao( new UserDaoOracleImpl() );
? ? service.getUser();
? }
這看起來(lái)可能沒(méi)有什么變化,但是他們已經(jīng)發(fā)生了根本的變化,很多地方都不一樣了,以前所有東西都是由程序去進(jìn)行控制創(chuàng)建,而現(xiàn)在是我們自行控制創(chuàng)建對(duì)象,把主動(dòng)權(quán)交給了調(diào)用者, 程序不用去管怎么創(chuàng)建,怎么實(shí)現(xiàn)了 . 它只負(fù)責(zé)提供一個(gè)接口 .
這種思想 , 從本質(zhì)上解決了問(wèn)題 , 我們程序員不再去管理對(duì)象的創(chuàng)建了 , 更多的去關(guān)注業(yè)務(wù)的實(shí)現(xiàn) . 耦合性大大降低 . 這也就是IOC的原型 !
IOC本質(zhì)
控制反轉(zhuǎn)IOC(Inversion of Control),是一種設(shè)計(jì)思想,DI(
)是實(shí)現(xiàn)IOC的一種方法,也有人認(rèn)為DI只是IOC的另一種說(shuō)法。沒(méi)有IOC的程序中 , 我們使用面向?qū)ο缶幊?, 對(duì)象的創(chuàng)建與對(duì)象間的依賴(lài)關(guān)系完全硬編碼在程序中,對(duì)象的創(chuàng)建由程序自己控制,控制反轉(zhuǎn)后將對(duì)象的創(chuàng)建轉(zhuǎn)移給第三方,個(gè)人認(rèn)為所謂控制反轉(zhuǎn)就是:獲得依賴(lài)對(duì)象的方式反轉(zhuǎn)了。
IOC是Spring框架的核心內(nèi)容,使用多種方式完美的實(shí)現(xiàn)了IOC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置實(shí)現(xiàn)IOC。
Spring容器在初始化時(shí)先讀取配置文件,根據(jù)配置文件或元數(shù)據(jù)創(chuàng)建與組織對(duì)象存入容器中,程序使用時(shí)再?gòu)腎oc容器中取出需要的對(duì)象。

采用XML方式配置Bean的時(shí)候,Bean的定義信息是和實(shí)現(xiàn)分離的,而采用注解的方式可以把兩者合為一體,Bean的定義信息直接以注解的形式定義在實(shí)現(xiàn)類(lèi)中,從而達(dá)到了零配置的目的。
控制反轉(zhuǎn)是一種通過(guò)描述(XML或注解)并通過(guò)第三方去生產(chǎn)或獲取特定對(duì)象的方式。在Spring中實(shí)現(xiàn)控制反轉(zhuǎn)的是IoC容器,其實(shí)現(xiàn)方法是依賴(lài)注入(Dependency Injection,DI)。
HelloSpring

導(dǎo)入Spring相關(guān)jar包
注 : spring 需要導(dǎo)入commons-logging進(jìn)行日志記錄 . 我們利用maven , 他會(huì)自動(dòng)下載對(duì)應(yīng)的依賴(lài)項(xiàng) .
? <dependency>
? ? <groupId>org.springframework</groupId>
? ? <artifactId>spring-webmvc</artifactId>
? ? <version>4.3.7.RELEASE</version>
? </dependency>
編寫(xiě)相關(guān)代碼
2.1編寫(xiě)一個(gè)Hello實(shí)體類(lèi)
?public class Hello {
? ? private String name;
?
? ? public String getName() {
? ? ? return name;
? ? }
? ? public void setName(String name) {
? ? ? this.name = name;
? ? }
?
? ? public void show(){
? ? ? System.out.println("Hello"+ name );
? ? }
? }
2.2 寫(xiě)編寫(xiě)我們的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就是java對(duì)象 , 由Spring創(chuàng)建和管理-->
?? ? ?<bean id="hello" class="com.kuang.pojo.Hello">
?? ? ? ?<property name="name" value="Spring"/>
? ? </bean>
?
? </beans>
2.3 我們可以去進(jìn)行測(cè)試了
?@Test
? public void test(){
? ? //解析beans.xml文件 , 生成管理相應(yīng)的Bean對(duì)象
? ? ApplicationContext context = newClassPathXmlApplicationContext("beans.xml");
? ? //getBean : 參數(shù)即為spring配置文件中bean的id .
? ? Hello hello = (Hello) context.getBean("hello");
? ? hello.show();
? }
這個(gè)過(guò)程就叫控制反轉(zhuǎn) :
控制 : 誰(shuí)來(lái)控制對(duì)象的創(chuàng)建 , 傳統(tǒng)應(yīng)用程序的對(duì)象是由程序本身控制創(chuàng)建的 , 使用Spring后 , 對(duì)象是由Spring來(lái)創(chuàng)建的 .
反轉(zhuǎn) : 程序本身不創(chuàng)建對(duì)象 , 而變成被動(dòng)的接收對(duì)象 .
依賴(lài)注入 : 就是利用set方法來(lái)進(jìn)行注入的.
IOC是一種編程思想 , 由主動(dòng)的編程變成被動(dòng)的接收 .
可以通過(guò)newClassPathXmlApplicationContext去瀏覽一下底層源碼 .
到了現(xiàn)在 , 我們徹底不用再程序中去改動(dòng)了 , 要實(shí)現(xiàn)不同的操作 , 只需要在xml配置文件中進(jìn)行修改 , 所謂的IoC,一句話搞定 : 對(duì)象由Spring 來(lái)創(chuàng)建 , 管理 , 裝配 !