最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解JavaSE實現(xiàn)IoC

 更新時間:2021年06月01日 09:30:24   作者:Grey Zeng  
簡單地說,IoC 是反轉(zhuǎn)控制,類似于好萊塢原則,主要有依賴查找和依賴注入實現(xiàn)。依賴查找是主動或手動的依賴查找方式,通常需要依賴容器或標(biāo)準(zhǔn)API實現(xiàn)。 而依賴注入則是手動或自動依賴綁定的方式,無需依賴特定的容器和API。本文將詳細(xì)介紹JavaSE實現(xiàn)IoC。

JavaSE中的IoC實現(xiàn)方式

Java SE 提供了三種方式,可以實現(xiàn)IoC,分別為:

  • Java Beans
  • Java ServiceLoader SPI
  • JNDI(Java Naming and Directory Interface)

Java Beans

java.beans包下的 Introspector 類提供了一個 getBeanInfo的方法,可以獲取一個類的信息

BeanInfo bi = Introspector.getBeanInfo(User.class,Object.class);

如上,則可以獲取User類對象的BeanInfo, 然后我們通過BeanInfo中的 getPropertyDescriptors 方法,可以獲取到User對象中的所有屬性和方法,

注意:java beans中,對于set(xxx)方法,統(tǒng)一叫:writeMethod(), 對于get() 方法,統(tǒng)一叫:readMethod()

Stream.of(bi.getPropertyDescriptors()).forEach(pd->{
        Class<?> propertyType=pd.getPropertyType();
        Method writeMethod=pd.getWriteMethod();
        });

獲取到方法和屬性名稱后,通過反射即可把對應(yīng)的值設(shè)置到對應(yīng)的屬性中

writeMethod.invoke(name,value);

由于我們注入屬性值的時候,我們注入的東西永遠(yuǎn)是一個字符串類型,如果需要注入的屬性是其他類型(非字符串), 比如User類中,有一個屬性是address,這個address是一個對象類型,我們應(yīng)該如何定義一個轉(zhuǎn)換器,將字符串類型的值轉(zhuǎn)換為我們需要的對象類型呢?

我們需要通過設(shè)置一個AddressEditor來實現(xiàn)這個轉(zhuǎn)換,這個AddressEditor有如下兩種實現(xiàn)方式:

實現(xiàn)PropertyEditor接口

繼承PropertyEditorSupport類,重寫setAsText方法

PropertyEditorSupport類提供了一些比較便利的實現(xiàn)方式,所以我們采用繼承PropertyEditorSupport類的方法,來實現(xiàn)類型的轉(zhuǎn)換,

Address類的設(shè)計是:

public class Address {
    private String name;
    private Integer num;
    // 省略 get / set / toString
}

我們的定義的規(guī)則如下,

輸入的字符串用|來分割 name 和 num屬性

例如: “貝克街|221” 這個字符串 會將“貝克街”賦給name,221賦給num,所以,我們重寫setAsText方法的邏輯如下:

public class AddressEditor extends PropertyEditorSupport {
    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        String[] tokens = text.split("\\|");
        Address address = new Address();
        address.setName(tokens[0]);
        address.setNum(Integer.valueOf(tokens[1]));
        setValue(address);
    }
}

同理,我們可以實現(xiàn)一個DateEditor,讓“yyyy-MM-dd”這樣類型的字符串轉(zhuǎn)換成日期格式。

public class DateEditor extends PropertyEditorSupport {

    static final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd");

    @Override
    public void setAsText(String text) throws IllegalArgumentException {
        LocalDate localDate = LocalDate.parse(text, dtf);
        ZoneId zone = ZoneId.systemDefault();
        Instant instant = localDate.atStartOfDay().atZone(zone).toInstant();
        setValue(Date.from(instant));
    }
}

然后,我們需要使用java beans中的PropertyEditorManager類的registerEditor方法把這兩個Editor注冊進(jìn)來

registerEditor(Address.class,AddressEditor.class);
registerEditor(Date.class,DateEditor.class);

最后,PropertyEditorManager的findEditor方法就可以根據(jù)我們前面得到的屬性類型,找到對應(yīng)的Editor來對值進(jìn)行轉(zhuǎn)換,轉(zhuǎn)換成我們需要的屬性類型的值

PropertyEditor editor=findEditor(propertyType);
if(editor!=null){
    // 這一步就是為所有屬性找到其對應(yīng)的解析器
    editor.setAsText(parameters.get(pd.getName()));
    try{
        writeMethod.invoke(user,editor.getValue());
    }catch(IllegalAccessException|InvocationTargetException e){
        e.printStackTrace();
    }
}else{
    System.out.println("no editor for:"+pd.getName());
}

主函數(shù)調(diào)用示例

public static void main(String[]args)throws Exception{
    Map<String, String> parameters=new HashMap<String, String>(){
        {
            //這里的key要和Node里面的屬性名一致
            put("name","福爾摩斯");
            put("address","貝克街|221");
            put("birthday","1854-01-06");
        }
    };
    User convert=PropertyEditorSample.convert(parameters);
    System.out.println(convert);
}

運(yùn)行結(jié)果

User{name='福爾摩斯', birthday=Thu Jan 05 23:54:17 CST 1854, address=Address{name='貝克街, 221 號}}

SPI

定義支付接口PayService

public interface PayService {
    void pay();
}

定義多個實現(xiàn):

public class WeixinpayService implements PayService {
    @Override
    public void pay() {
        System.out.println("微信支付");
    }
}
public class AlipayService implements PayService {
    @Override
    public void pay() {
        System.out.println("支付寶支付");
    }
}

在resources目錄下建立META-INF文件夾,在META-INF文件夾下建立services目錄,同時建立一個文件,名稱為接口的全路徑名,以這個項目為例, PayService的全路徑名稱為:

org.snippets.ioc.java.spi.PayService

在這個文件內(nèi),把實現(xiàn)類的全路徑名寫進(jìn)去:

org.snippets.ioc.java.spi.AlipayService
org.snippets.ioc.java.spi.WeixinpayService

客戶端調(diào)用:

ServiceLoader<PayService> serviceLoader=ServiceLoader.load(PayService.class);

for(PayService ele:serviceLoader){
    ele.pay();
}

其中ServiceLoader.load方法可以把所有配置的PayService實現(xiàn)得到

執(zhí)行結(jié)果:

支付寶支付

微信支付

JNDI方式

定義一個Person類

public class Person implements Remote, Serializable {

    private static final long serialVersionUID = 1L;
    private String name;
    private String password;

    // 省略set / get方法
}

實現(xiàn)JNDI的客戶端,實現(xiàn)初始化Person和查找Person兩個功能

public static void initPerson()throws Exception{
    //配置JNDI工廠和JNDI的url和端口。如果沒有配置這些信息,將會出現(xiàn)NoInitialContextException異常
    LocateRegistry.createRegistry(3000);
    System.setProperty(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.rmi.registry.RegistryContextFactory");
    System.setProperty(Context.PROVIDER_URL,"rmi://localhost:3000");


    InitialContext ctx=new InitialContext();

    //實例化person對象
    Person p=new Person();
    p.setName("zc");
    p.setPassword("123");

    //將person對象綁定到JNDI服務(wù)中,JNDI的名字叫做:person。
    ctx.bind("person",p);
    ctx.close();
}

public static void findPerson()throws Exception{
    //因為前面已經(jīng)將JNDI工廠和JNDI的url和端口已經(jīng)添加到System對象中,這里就不用在綁定了
    InitialContext ctx=new InitialContext();

    //通過lookup查找person對象
    Person person=(Person)ctx.lookup("person");

    //打印出這個對象
    System.out.println(person.toString());
    ctx.close();
}

以上就是詳解JavaSE實現(xiàn)IoC的詳細(xì)內(nèi)容,更多關(guān)于JavaSE實現(xiàn)IoC的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Spring和SpringMVC父子容器關(guān)系初窺(小結(jié))

    Spring和SpringMVC父子容器關(guān)系初窺(小結(jié))

    這篇文章主要介紹了Spring和SpringMVC父子容器關(guān)系初窺(小結(jié)),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • 如何將默認(rèn)的maven倉庫改為阿里的maven倉庫

    如何將默認(rèn)的maven倉庫改為阿里的maven倉庫

    這篇文章主要介紹了如何將默認(rèn)的maven倉庫改為阿里的maven倉庫,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • Spring循環(huán)依賴的處理方法

    Spring循環(huán)依賴的處理方法

    循環(huán)依賴是指兩個或多個組件之間相互依賴,形成一個閉環(huán),從而導(dǎo)致這些組件無法正確地被初始化或加載,這篇文章主要介紹了Spring循環(huán)依賴的處理,需要的朋友可以參考下
    2023-08-08
  • java算法之Math.random()隨機(jī)概率玩法實例演示

    java算法之Math.random()隨機(jī)概率玩法實例演示

    最近打算整理排序算法,發(fā)現(xiàn)很有必要準(zhǔn)備一下生成隨機(jī)數(shù)的工具類,下面這篇文章主要給大家介紹了關(guān)于java算法之Math.random()隨機(jī)概率玩法的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • Java聊天室之實現(xiàn)使用Socket傳遞音頻

    Java聊天室之實現(xiàn)使用Socket傳遞音頻

    這篇文章主要為大家詳細(xì)介紹了Java簡易聊天室之使用Socket實現(xiàn)傳遞音頻功能,文中的示例代碼講解詳細(xì),具有一定的借鑒價值,需要的可以了解一下
    2022-10-10
  • JAVA設(shè)計模式---單例模式你知道嗎

    JAVA設(shè)計模式---單例模式你知道嗎

    這篇文章主要給大家介紹了關(guān)于Java單例模式,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用Java具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-09-09
  • 初識Java基礎(chǔ)之?dāng)?shù)據(jù)類型與運(yùn)算符

    初識Java基礎(chǔ)之?dāng)?shù)據(jù)類型與運(yùn)算符

    Java是一種強(qiáng)類型語言,每個變量都必須聲明其數(shù)據(jù)類型,下面這篇文章主要給大家介紹了關(guān)于Java基礎(chǔ)之?dāng)?shù)據(jù)類型與運(yùn)算符的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-10-10
  • Java簡易計算器程序設(shè)計

    Java簡易計算器程序設(shè)計

    這篇文章主要為大家詳細(xì)介紹了Java簡易計算器程序設(shè)計的相關(guān)參考資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2015-10-10
  • 關(guān)于QueryWrapper,實現(xiàn)MybatisPlus多表關(guān)聯(lián)查詢方式

    關(guān)于QueryWrapper,實現(xiàn)MybatisPlus多表關(guān)聯(lián)查詢方式

    這篇文章主要介紹了關(guān)于QueryWrapper,實現(xiàn)MybatisPlus多表關(guān)聯(lián)查詢方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教。
    2022-01-01
  • java枚舉轉(zhuǎn)list通用類過程

    java枚舉轉(zhuǎn)list通用類過程

    文章介紹了如何將Java枚舉類型轉(zhuǎn)換為List<Map<String, Object>>的通用類,該類可以實現(xiàn)枚舉到列表的轉(zhuǎn)換,并且示例了使用方法
    2025-03-03

最新評論

沙雅县| 理塘县| 台湾省| 武山县| 浙江省| 济源市| 奎屯市| 金寨县| 上林县| 桐柏县| 和静县| 荔波县| 桐梓县| 宝丰县| 高州市| 大洼县| 冀州市| 女性| 都兰县| 民丰县| 岑巩县| 栾川县| 牙克石市| 方山县| 大荔县| 临安市| 班戈县| 抚州市| 金湖县| 九寨沟县| 登封市| 嘉善县| 银川市| 廉江市| 黄平县| 崇义县| 仪陇县| 青河县| 霞浦县| 西安市| 齐齐哈尔市|