国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Spring理論基礎(chǔ)-控制反轉(zhuǎn)和依賴注入

FullStackDeveloper / 1400人閱讀

摘要:控制反轉(zhuǎn)和依賴注入的關(guān)系也已經(jīng)清晰了,它們本質(zhì)上可以說是一樣的,只是具體的關(guān)注點不同。我的博客地址參考資料控制反轉(zhuǎn)和依賴注入的理解那些年搞不懂的高深術(shù)語依賴倒置控制反轉(zhuǎn)依賴注入面向接口編程控制反轉(zhuǎn)和依賴注入

第一次了解到控制反轉(zhuǎn)(Inversion of Control)這個概念,是在學(xué)習(xí)Spring框架的時候。IOCAOP作為Spring的兩大特征,自然是要去好好學(xué)學(xué)的。而依賴注入(Dependency Injection,簡稱DI)卻使得我困惑了挺久,一直想不明白他們之間的聯(lián)系。

控制反轉(zhuǎn)

控制反轉(zhuǎn)顧名思義,就是要去反轉(zhuǎn)控制權(quán),那么到底是哪些控制被反轉(zhuǎn)了?在2004年 Martin fowler 大神就提出了

“哪些方面的控制被反轉(zhuǎn)了?”

這個問題,他總結(jié)出是依賴對象的獲得被反轉(zhuǎn)了。

在單一職責原則的設(shè)計下,很少有多帶帶一個對象就能完成的任務(wù)。大多數(shù)任務(wù)都需要復(fù)數(shù)的對象來協(xié)作完成,這樣對象與對象之間就有了依賴。一開始對象之間的依賴關(guān)系是自己解決的,需要什么對象了就New一個出來用,控制權(quán)是在對象本身。但是這樣耦合度就非常高,可能某個對象的一點小修改就會引起連鎖反應(yīng),需要把依賴的對象一路修改過去。

如果依賴對象的獲得被反轉(zhuǎn),具體生成什么依賴對象和什么時候生成都由對象之外的IOC容器來決定。對象只要在用到依賴對象的時候能獲取到就可以了,常用的方式有依賴注入和依賴查找(Dependency Lookup)。這樣對象與對象之間的耦合就被移除到了對象之外,后續(xù)即使有依賴修改也不需要去修改原代碼了。

總結(jié)一下,控制反轉(zhuǎn)是指把對象的依賴管理從內(nèi)部轉(zhuǎn)移至外部。

依賴注入

控制反轉(zhuǎn)是把對象之間的依賴關(guān)系提到外部去管理,可依賴是提到對象外面了,對象本身還是要用到依賴對象的,這時候就要用到依賴注入了。顧名思義,應(yīng)用需要把對象所需要的依賴從外部注入進來。可以是通過對象的構(gòu)造函數(shù)傳參注入,這種叫做構(gòu)造器注入(Constructor Injection)。如果是通過JavaBean的屬性方法傳參注入,就叫做設(shè)值方法注入(Setter Injection)

不管是通過什么方式注入的,如果是我們手動注入的話還是顯得太麻煩了。這時候就需要一個容器來幫我們實現(xiàn)這個功能,自動的將對象所需的依賴注入進去,這個容器就是前面提到的IOC容器了。

控制反轉(zhuǎn)和依賴注入的關(guān)系也已經(jīng)清晰了,它們本質(zhì)上可以說是一樣的,只是具體的關(guān)注點不同。控制反轉(zhuǎn)的關(guān)注點是控制權(quán)的轉(zhuǎn)移,而依賴注入則內(nèi)含了控制反轉(zhuǎn)的意義,明確的描述了依賴對象在外部被管理然后注入到對象中。實現(xiàn)了依賴注入,控制也就反轉(zhuǎn)了。

例子

首先是傳統(tǒng)的方式,耦合非常嚴重。

public class Main {

    public static void main(String[] args) {
        OrderService service = new OrderService();
        service.test();
    }

}
public class OrderService {

    private OrderDao dao = new OrderDao();

    public void test() {
        dao.doSomeThing();
    }

}
public class OrderDao {

    public void doSomeThing() {
        System.out.println("test");
    }

}

接下來是沒有使用容器的方式,松耦合了,但是手動注入非常的麻煩。

public class Main {

    public static void main(String[] args) {
        Dao dao = new OrderDao();
        OrderService service = new OrderService(dao);
        service.test();
    }

}
public interface Dao {

    void doSomeThing();

}
public class OrderDao implements Dao {

    @Override
    public void doSomeThing() {
        System.out.println("test");
    }

}
public class OrderService {

    private Dao dao;

    public OrderService(Dao dao) {
        this.dao = dao;
    }

    public void test() {
        dao.doSomeThing();
    }

}

接下來使用容器造福人類。

// 引導(dǎo)類要放在項目根目錄下,也就是在 src 下面
public class Main {

    public static void main(String[] args) {
        // 生成容器
        Container container = new Container(Main.class);
        // 獲取Bean
        OrderService service = container.getBean(OrderService.class);
        // 調(diào)用
        service.test();
    }

}
@Component
public class OrderService {

    @Autowired
    private Dao dao;

    public void test() {
        dao.doSomeThing();
    }

    public Dao getDao() {
        return dao;
    }

    public void setDao(Dao dao) {
        this.dao = dao;
    }
}
@Component
public class OrderDao implements Dao {

    @Override
    public void doSomeThing() {
        System.out.println("test");
    }

}
public interface Dao {

    void doSomeThing();

}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Component {
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.METHOD})
public @interface Autowired {
}
public class Container {

    private List classPaths = new ArrayList<>();

    private String separator;

    private Map components = new HashMap<>();

    public Container(Class cls) {
        File file = new File(cls.getResource("").getFile());
        separator = file.getName();
        renderClassPaths(new File(this.getClass().getResource("").getFile()));
        make();
        di();
    }

    private void make() {
        classPaths.forEach(classPath -> {
            try {
                Class c = Class.forName(classPath);
                // 找到有 @ioc.Component 注解的類并實例化
                if (c.isAnnotationPresent(Component.class)) {
                    components.put(c, c.newInstance());
                }
            } catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
                e.printStackTrace();
            }
        });
    }

    /**
     * 注入依賴
     */
    private void di() {
        components.forEach((aClass, o) -> Arrays.stream(aClass.getDeclaredFields()).forEach(field -> {
            if (field.isAnnotationPresent(Autowired.class)) {
                try {
                    String methodName = "set" + field.getType().getName().substring(field.getType().getName().lastIndexOf(".") + 1);
                    Method method = aClass.getMethod(methodName, field.getType());
                    if (field.getType().isInterface()) {
                        components.keySet().forEach(aClass1 -> {
                            if (Arrays.stream(aClass1.getInterfaces()).anyMatch(aClass2 -> aClass2.equals(field.getType()))) {
                                try {
                                    method.invoke(o, components.get(aClass1));
                                } catch (IllegalAccessException | InvocationTargetException e) {
                                    e.printStackTrace();
                                }
                            }
                        });
                    } else {
                        method.invoke(o, components.get(field.getType()));
                    }
                } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            }
        }));
    }

    /**
     * 該方法會得到所有的類,將類的全類名寫入到classPaths中
     *
     * @param file 包
     */
    private void renderClassPaths(File file) {
        if (file.isDirectory()) {
            File[] files = file.listFiles();
            Arrays.stream(Objects.requireNonNull(files)).forEach(this::renderClassPaths);
        } else {
            if (file.getName().endsWith(".class")) {
                String classPath = file.getPath()
                        .substring(file.getPath().lastIndexOf(separator) + separator.length() + 1)
                        .replace("", ".")
                        .replace(".class", "");
                classPaths.add(classPath);
            }
        }
    }

    public  T getBean(Class c) {
        return (T) components.get(c);
    }

}
后記

一些概念在腦海里總以為是清晰的,等實際用到或者是寫成文字的時候就發(fā)現(xiàn)有很多不理解的地方。本文的目的就是梳理下概念,做些記錄。這次自己嘗試實現(xiàn)了下IOC容器,一開始寫就知道自己之前的理解有問題了。好歹是寫出了個能用的版本,用來應(yīng)付文章中的例子。后面可以去參考下Spring的實現(xiàn),估計能學(xué)到不少東西。

我的博客地址

參考資料

控制反轉(zhuǎn)和依賴注入的理解

那些年搞不懂的高深術(shù)語——依賴倒置?控制反轉(zhuǎn)?依賴注入?面向接口編程

控制反轉(zhuǎn)(IOC)和依賴注入(DI)

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/71476.html

相關(guān)文章

  • Spring還可以這么學(xué)--IoC(控制反轉(zhuǎn)) / DI(依賴注入)理解

    摘要:對象之間耦合度過高的系統(tǒng),必然會出現(xiàn)牽一發(fā)而動全身的情形。控制被反轉(zhuǎn)之后,獲得依賴對象的過程由自身管理變?yōu)榱擞扇萜髦鲃幼⑷搿S谑牵o控制反轉(zhuǎn)取了一個更合適的名字叫做依賴注入。 Spring還可以這么學(xué)--IoC(控制反轉(zhuǎn)) / DI(依賴注入)理解 聲明:文章的前三部分參考博文:https://www.cnblogs.com/Nouno...這篇文章首發(fā)是在我的個人微信訂閱號每天學(xué)編...

    atinosun 評論0 收藏0
  • Spring框架學(xué)習(xí)筆記(一):官方文檔介紹,IoC與AOP概念學(xué)習(xí)

    摘要:構(gòu)造函數(shù)注入通過調(diào)用類的構(gòu)造函數(shù),將接口實現(xiàn)類通過構(gòu)造函數(shù)變量傳入。而在中,其使用橫切技術(shù),將這類代碼從原屬的封裝對象中提取出來,封裝到一個可重用模塊中,稱為。 最近實習(xí)用到Spring的開發(fā)框架,但是之前沒有接觸過,因此希望利用網(wǎng)上的資源來學(xué)習(xí)以下。 Spring官方給出了非常全面的介紹,非常適合我這種完全的小白……在這一系列學(xué)習(xí)中,我閱讀的主要資源是5.1.2 Reference ...

    mindwind 評論0 收藏0
  • 基礎(chǔ)帶你看Spring源碼——IOC控制反轉(zhuǎn)

    摘要:依賴注入是向某個類或方法注入一個值,其中所用到的原理就是控制反轉(zhuǎn)。但發(fā)現(xiàn)更多時間是在調(diào)和的源碼。里面就是從中取出這個,完成控制反轉(zhuǎn)的。控制反轉(zhuǎn)的優(yōu)點最后來以我個人觀點談?wù)効刂品崔D(zhuǎn)的優(yōu)點吧。控制反轉(zhuǎn)為了降低項目耦合,提高延伸性。 本章開始來學(xué)習(xí)下Spring的源碼,看看Spring框架最核心、最常用的功能是怎么實現(xiàn)的。網(wǎng)上介紹Spring,說源碼的文章,大多數(shù)都是生搬硬推,都是直接看來的...

    wing324 評論0 收藏0
  • Spring IoC學(xué)習(xí)總結(jié)

    摘要:學(xué)習(xí)總結(jié)學(xué)習(xí)整理的一些筆記,很簡單。大部分認為和只是不同的叫法而已。依賴注入的兩種方式和注解使用注釋驅(qū)動的功能源碼剖析 Spring IoC學(xué)習(xí)總結(jié) 學(xué)習(xí)spring Ioc整理的一些筆記,很簡單。分享給大家。 IoC 基本概念 在這之前,我們先記住一句話。好萊塢原則:Dont call us, we will call you.其實這句話很恰當?shù)匦稳萘朔崔D(zhuǎn)的意味;Ioc, Inve...

    silencezwm 評論0 收藏0
  • Spring IOC知識點一網(wǎng)打盡!

    摘要:使用的好處知乎的回答不用自己組裝,拿來就用。統(tǒng)一配置,便于修改。 前言 只有光頭才能變強 回顧前面: 給女朋友講解什么是代理模式 包裝模式就是這么簡單啦 單例模式你會幾種寫法? 工廠模式理解了沒有? 在刷Spring書籍的時候花了點時間去學(xué)習(xí)了單例模式和工廠模式,總的來說還是非常值得的! 本來想的是刷完《Spring 實戰(zhàn) (第4版)》和《精通Spring4.x 企業(yè)應(yīng)用開發(fā)實戰(zhàn)》...

    djfml 評論0 收藏0

發(fā)表評論

0條評論

FullStackDeveloper

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<