欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解JavaSE實現(xiàn)IoC

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

由于我們注入屬性值的時候,我們注入的東西永遠是一個字符串類型,如果需要注入的屬性是其他類型(非字符串), 比如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注冊進來

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

最后,PropertyEditorManager的findEditor方法就可以根據(jù)我們前面得到的屬性類型,找到對應(yīng)的Editor來對值進行轉(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);
}

運行結(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)類的全路徑名寫進去:

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的詳細內(nèi)容,更多關(guān)于JavaSE實現(xiàn)IoC的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 詳解Java設(shè)計模式編程中的Flyweight享元模式的開發(fā)結(jié)構(gòu)

    詳解Java設(shè)計模式編程中的Flyweight享元模式的開發(fā)結(jié)構(gòu)

    這篇文章主要介紹了Java設(shè)計模式編程中的Flyweight享元模式的開發(fā)結(jié)構(gòu),享元模式能夠最大限度地重用現(xiàn)有的同類對象,需要的朋友可以參考下
    2016-04-04
  • 淺談web項目讀取classpath路徑下面的文件

    淺談web項目讀取classpath路徑下面的文件

    這篇文章主要介紹了淺談web項目讀取classpath路徑下面的文件,具有一定借鑒價值,需要的朋友可以參考下
    2018-01-01
  • 基于MapperXML掃描的問題

    基于MapperXML掃描的問題

    這篇文章主要介紹了MapperXML掃描的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Windows7下的Java運行環(huán)境搭建過程圖解

    Windows7下的Java運行環(huán)境搭建過程圖解

    這篇文章主要介紹了Windows7下的Java運行環(huán)境搭建過程圖解,需要的朋友可以參考下
    2014-04-04
  • java8中的lambda表達式,看這篇絕對夠

    java8中的lambda表達式,看這篇絕對夠

    這篇文章主要介紹了java8中的lambda表達式,看這篇絕對夠!具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-03-03
  • SpringBoot登錄、退出、獲取用戶信息的session處理方案

    SpringBoot登錄、退出、獲取用戶信息的session處理方案

    這篇文章主要介紹了SpringBoot登錄、退出、獲取用戶信息的session處理,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-08-08
  • springMVC在restful風(fēng)格的性能優(yōu)化方案

    springMVC在restful風(fēng)格的性能優(yōu)化方案

    這篇文章主要介紹了springMVC在restful風(fēng)格的性能優(yōu)化方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-08-08
  • 詳解如何使用Java8?Steam流對Map進行排序

    詳解如何使用Java8?Steam流對Map進行排序

    這篇文章主要給大家詳細介紹了如何使用Java8?Steam流對Map進行排序,文中通過代碼示例講解的非常詳細,對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2024-01-01
  • Mybatis中特殊SQL的執(zhí)行

    Mybatis中特殊SQL的執(zhí)行

    這篇文章主要介紹了Mybatis中特殊SQL的執(zhí)行,介紹內(nèi)容包括模糊查詢、批量刪除、動態(tài)設(shè)置表名、添加功能獲取自增的主鍵等相關(guān)資料,需要的小伙伴可以參考一下
    2022-04-04
  • JAVA面試題 start()和run()詳解

    JAVA面試題 start()和run()詳解

    這篇文章主要介紹了JAVA面試題 啟動線程是start()還是run()?為什么?,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07

最新評論