天天看點

spring之lookup-method、replaced-method

在開發中大部分使用到的Bean對象都是單例的,如果有一單例對象依賴一多執行個體對象時。由于Spring容器在啟動後就初始化好了單執行個體對象,是以依賴的多執行個體對象也會進行建立好,但是這樣會造成一個問題即:單執行個體對象有且僅有一次機會裝配這個多執行個體對象

lookup-method 注入底層是依賴了CGLIB 庫提供的方法可以實作動态Bean的實作,下面是其簡單示例需求:

有一電子工廠可以生産電子産品例如手機、電腦等,電子經銷商希望每次進貨的時候都可以拿到最新生産的産品。

xml的配置

測試:

上述使用的xml配置進行實作,也可以使用注解去實作如下所示:

修改手機類與電腦類如下

抽象工廠類

注意:

以上我們并沒有實作此createProduct()抽象方法但是運作結果依然可以生産手機或者電腦,這是由于Spring底層使用CGLIB代理動态生成了此抽象工廠的子類以及重寫實作了其抽象方法。這裡需要注意的是代理的對象不能是final修飾,其方法也不能是final修飾。否則Spring無法使用CGLIB代理動态生成子類方法建立對象。是以一般我們将被代理的類設定為抽象類,被代理類的方法設定為抽象方法,而且除此之外需要注意的是一般注入的對象的scope 設定為多執行個體的,否則每次生成的都是同一對象。

replace-method

replace-method是Spring 動态借助CGLIB改變bean中的方法,通過改變方法邏輯注入對象,該方法的使用需要依賴Spring提供的MethodReplacer 接口實作。

定義一個列印輸出使用者名的方法然後使用replace-method 改變方法的輸出值

定義接口以及原生實作

xml配置

看到MethodReplacer 的實作是不是感覺和JDK的InvocationHandler接口非常類似呢?其實可以知道Spring的實作也是使用了反射以及底層CGLIB的實作完成方法替換。

lookup-method與@Autowired依賴注入的差別

Autowired用于給一個單例對象注入另一個單例對象。 但是無法注入另外一個多執行個體對象,這是由于單例的bean隻會初始化一次,是以這個多執行個體bean實際上可以看成是一個“單例bean”。除了可以使用applicationContext.getBean去擷取最新的執行個體對象,最完美的方式是使用lookup-method 完成注入,由于采用CGLIB底層動态實作類以及重寫類方法可以完美做到零耦合,開發中建議使用此種方式完成方法注入。