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

Springboot使用SPI注冊bean到spring容器的示例代碼

 更新時間:2022年10月10日 10:06:40   作者:Vidor_Chan  
這篇文章主要介紹了Springboot使用SPI注冊bean到spring容器,主要包括mydriver接口,mysqldriver實現(xiàn)過程,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下

新建resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
  com.ExtensionLoader

新建META-INF/vtest/全路徑接口名

mysqlDriver=com.MysqlDriver
oracleDriver=com.OracleDriver

 MyDriver接口

public interface MyDriver {
    void getConnect();
}

MysqlDriver實現(xiàn)

public class MysqlDriver implements MyDriver{
    @Override
    public void getConnect() {
        System.out.println("connect");
    }
}

OracleDriver實現(xiàn)

public class OracleDriver implements MyDriver{
    @Override
    public void getConnect() {
        System.out.println("connect");
    }
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.util.StringUtils;
 
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
 
public class ExtensionLoader implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
 
    ApplicationContext context;
 
    BeanDefinitionRegistry beanDefinitionRegistry;
 
    ConcurrentHashMap<Class<?>, Map<String, Object>> EXTENSIONS = new ConcurrentHashMap<>();
 
    private static final String SPI_DIRECTORY = "META-INF/vtest/";
 
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
 
        ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) context;
        beanDefinitionRegistry = (DefaultListableBeanFactory) configurableApplicationContext.getBeanFactory();
    }
 
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        try {
            ClassLoader classLoader = DefaultListableBeanFactory.class.getClassLoader();
            URL resource;
            File[] files;
 
            if (classLoader != null) {
                resource = classLoader.getResource(this.SPI_DIRECTORY);
            } else {
                resource = ClassLoader.getSystemResource(this.SPI_DIRECTORY);
            }
 
            files = new File(resource.getFile()).listFiles();
 
            for (int i = 0; i < files.length; i++) {
                Class<?> clazz = Class.forName(files[i].getName(), true, classLoader);
                EXTENSIONS.putIfAbsent(clazz, loadExtensionClass(clazz.getName()));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
 
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
 
    }
 
    /**
     * 獲取某個接口類型對應的實現(xiàn)
     *
     * @param type
     * @return
     */
    public Map<String, Object> getExtensions(Class type) {
        if (null == type) {
            throw new IllegalArgumentException("Extension Class is null");
        }
 
        if (!type.isInterface()) {
            throw new IllegalArgumentException("Extension Class is not an interface");
        }
 
        Map<String, Object> loader = EXTENSIONS.get(type);
        if (loader == null) {
            synchronized (ExtensionLoader.class) {
                loader = EXTENSIONS.get(type);
                if (loader == null) {
                    EXTENSIONS.putIfAbsent(type, loadExtensionClass(type.getName()));
                    loader = EXTENSIONS.get(type);
                }
            }
        }
        return loader;
    }
 
    /**
     * 從擴展文件中加載類
     *
     * @param type
     * @return
     */
    private Map<String, Object> loadExtensionClass(String type) {
        Map<String, Object> extensionClasses = new HashMap<>();
        loadDirectory(extensionClasses, SPI_DIRECTORY, type);
        return extensionClasses;
    }
 
    /**
     * 加載文件夾
     *
     * @param extensionClasses
     * @param dir
     * @param type
     */
    private void loadDirectory(Map<String, Object> extensionClasses, String dir, String type) {
        String fileName = dir + type;
        try {
            Enumeration<URL> urls;
            ClassLoader classLoader = DefaultListableBeanFactory.class.getClassLoader();
            if (classLoader != null) {
                urls = classLoader.getResources(fileName);
            } else {
                urls = ClassLoader.getSystemResources(fileName);
            }
            if (urls != null) {
                while (urls.hasMoreElements()) {
                    URL resourcesURL = urls.nextElement();
                    loadResources(extensionClasses, classLoader, resourcesURL);
                }
            }
        } catch (Throwable t) {
        }
    }
 
    private void loadResources(Map<String, Object> extensionClasses, ClassLoader classLoader, URL resourceURL) {
        try {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(resourceURL.openStream(), StandardCharsets.UTF_8))) {
                String line;
                while ((line = reader.readLine()) != null) {
                    final int ci = line.indexOf('#');
                    if (ci >= 0) {
                        line = line.substring(0, ci);
                    }
                    line = line.trim();
                    if (line.length() > 0) {
                        try {
                            String name = null;
                            int i = line.indexOf('=');
                            if (i > 0) {
                                name = line.substring(0, i).trim();
                                line = line.substring(i + 1).trim();
                            }
                            if (line.length() > 0) {
                                loadClass(extensionClasses, resourceURL, Class.forName(line, true, classLoader), name);
                            }
                        } catch (Throwable t) {
                            IllegalStateException e = new IllegalStateException("Failed to load extension class (class line: " + line + ") in " + resourceURL + ", cause: " + t.getMessage(), t);
                        }
                    }
                }
            }
        } catch (Throwable t) {
        }
    }
 
    private void loadClass(Map<String, Object> extensionClasses, java.net.URL resourceURL, Class<?> clazz, String name) {
        if (StringUtils.isEmpty(name)) {
            throw new IllegalStateException("No such extension name for the class " + name + " in the config " + resourceURL);
        }
        Object o = extensionClasses.get(name);
        if (o == null) {
            Object bean = injectBeanToSpring(name, clazz);
            extensionClasses.put(name, bean);
        } else {
            throw new IllegalStateException("Duplicate extension name " + name + " on " + clazz.getName() + " and " + clazz.getName());
        }
    }
 
    /**
     * 動態(tài)注入bean到spring容器
     *
     * @param name
     * @param obj
     * @return
     */
    private Object injectBeanToSpring(String name, Class<?> obj) {
        String beanName = name;
 
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(obj);
        GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
        definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_NAME);
        beanDefinitionRegistry.registerBeanDefinition(beanName, definition);
 
        // TODO: 2020/1/9  這里動態(tài)注入的bean并未將內(nèi)部的@Autowired的bean依賴注入進去,如何解決?
 
        // 通過反射設置@Autowired標記的字段的值
 
        Object bean = context.getBean(beanName);
 
        Field[] declaredFields = obj.getDeclaredFields();
        for (Field field : declaredFields) {
            if (field.isAnnotationPresent(Autowired.class)) {
                Object aClass = context.getBean(field.getType());
 
                ReflectHelper.setFieldValue(bean, field.getName(), aClass);
            }
        }
 
        return bean;
    }
}
public class ReflectHelper {
 
    /**
     * 利用反射獲取指定對象的指定屬性
     *
     * @param obj       目標對象
     * @param fieldName 目標屬性
     * @return 目標屬性的值
     */
    public static Object getFieldValue(Object obj, String fieldName) {
        Object result = null;
        Field field = ReflectHelper.getField(obj, fieldName);
        if (field != null) {
            field.setAccessible(true);
            try {
                result = field.get(obj);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return result;
    }
 
    /**
     * 利用反射獲取指定對象里面的指定屬性
     *
     * @param obj       目標對象
     * @param fieldName 目標屬性
     * @return 目標字段
     */
    private static Field getField(Object obj, String fieldName) {
        Field field = null;
        for (Class<?> clazz = obj.getClass(); clazz != Object.class; clazz = clazz.getSuperclass()) {
            try {
                field = clazz.getDeclaredField(fieldName);
                break;
            } catch (NoSuchFieldException e) {
                //這里不用做處理,子類沒有該字段可能對應的父類有,都沒有就返回null。
            }
        }
        return field;
    }
 
    /**
     * 利用反射設置指定對象的指定屬性為指定的值
     *
     * @param obj        目標對象
     * @param fieldName  目標屬性
     * @param fieldValue 目標值
     */
    public static void setFieldValue(Object obj, String fieldName,
                                     Object fieldValue) {
        Field field = ReflectHelper.getField(obj, fieldName);
        if (field != null) {
            try {
                field.setAccessible(true);
                field.set(obj, fieldValue);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

Controller:

@RestController
@RequestMapping("/t")
@Api(value = "測試服務", description = "")
public class TestController {
 
	// 切換不同的服務
    @Autowired
    @Qualifier("mysqlDriver")
    private MyDriver myDriver;
 
    @ApiOperation(value = "測試", notes = "基于SPRING BOOT實現(xiàn)的JAVA SPI機制的DEMO")
    @GetMapping("/spi")
    public String test() {
        myDriver.getConnect();
 
        return "ok";
    }
}

到此這篇關于Springboot使用SPI注冊bean到spring容器的文章就介紹到這了,更多相關Springboot注冊bean內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Java 繼承與多態(tài)超詳細梳理

    Java 繼承與多態(tài)超詳細梳理

    繼承就是可以直接使用前輩的屬性和方法。自然界如果沒有繼承,那一切都是處于混沌狀態(tài)。多態(tài)是同一個行為具有多個不同表現(xiàn)形式或形態(tài)的能力。多態(tài)就是同一個接口,使用不同的實例而執(zhí)行不同操作
    2022-04-04
  • 如何使用Java調用Spark集群

    如何使用Java調用Spark集群

    這篇文章主要介紹了如何使用Java調用Spark集群,我搭建的Spark集群的版本是2.4.4,本文結合示例代碼給大家介紹的非常詳細,感興趣的朋友跟隨小編一起看看吧
    2024-02-02
  • 淺談spring中的default-lazy-init參數(shù)和lazy-init

    淺談spring中的default-lazy-init參數(shù)和lazy-init

    下面小編就為大家?guī)硪黄獪\談spring中的default-lazy-init參數(shù)和lazy-init。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-04-04
  • 關于Java利用反射實現(xiàn)動態(tài)運行一行或多行代碼

    關于Java利用反射實現(xiàn)動態(tài)運行一行或多行代碼

    這篇文章主要介紹了關于Java利用反射實現(xiàn)動態(tài)運行一行或多行代碼,借鑒了別人的方法和書上的內(nèi)容,最后將題目完成了,和大家一起分享以下解決方法,需要的朋友可以參考下
    2023-04-04
  • Spring中@Transactional用法詳細介紹

    Spring中@Transactional用法詳細介紹

    這篇文章主要介紹了Spring中@Transactional用法詳細介紹的相關資料,需要的朋友可以參考下
    2017-02-02
  • Java線程公平鎖和非公平鎖的差異講解

    Java線程公平鎖和非公平鎖的差異講解

    今天小編就為大家分享一篇關于Java線程公平鎖和非公平鎖的差異講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例

    SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例

    規(guī)則引擎其實是一種組件,它可以嵌入到程序當中,將程序復雜的判斷規(guī)則從業(yè)務代碼中剝離出來,使得程序只需要關心自己的業(yè)務,而不需要去進行復雜的邏輯判斷,本文給大家介紹了SpringBoot+URule實現(xiàn)可視化規(guī)則引擎的方法示例,需要的朋友可以參考下
    2024-12-12
  • Java如何向主函數(shù)main中傳入?yún)?shù)

    Java如何向主函數(shù)main中傳入?yún)?shù)

    這篇文章主要介紹了Java如何向主函數(shù)main中傳入?yún)?shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • 解決SpringBoot返回結果如果為null或空值不顯示處理問題

    解決SpringBoot返回結果如果為null或空值不顯示處理問題

    這篇文章主要介紹了解決SpringBoot返回結果如果為null或空值不顯示處理問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • Java?時間相減算法題解示例

    Java?時間相減算法題解示例

    這篇文章主要為大家介紹了Java?時間相減算法題解示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12

最新評論