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

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

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

新建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 {
 
    }
 
    /**
     * 獲取某個接口類型對應(yīng)的實現(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;
    }
 
    /**
     * 從擴(kuò)展文件中加載類
     *
     * @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依賴注入進(jìn)去,如何解決?
 
        // 通過反射設(shè)置@Autowired標(biāo)記的字段的值
 
        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       目標(biāo)對象
     * @param fieldName 目標(biāo)屬性
     * @return 目標(biāo)屬性的值
     */
    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       目標(biāo)對象
     * @param fieldName 目標(biāo)屬性
     * @return 目標(biāo)字段
     */
    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) {
                //這里不用做處理,子類沒有該字段可能對應(yīng)的父類有,都沒有就返回null。
            }
        }
        return field;
    }
 
    /**
     * 利用反射設(shè)置指定對象的指定屬性為指定的值
     *
     * @param obj        目標(biāo)對象
     * @param fieldName  目標(biāo)屬性
     * @param fieldValue 目標(biāo)值
     */
    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 = "測試服務(wù)", description = "")
public class TestController {
 
	// 切換不同的服務(wù)
    @Autowired
    @Qualifier("mysqlDriver")
    private MyDriver myDriver;
 
    @ApiOperation(value = "測試", notes = "基于SPRING BOOT實現(xiàn)的JAVA SPI機(jī)制的DEMO")
    @GetMapping("/spi")
    public String test() {
        myDriver.getConnect();
 
        return "ok";
    }
}

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

相關(guān)文章

  • MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn)

    MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn)

    本文主要介紹了MyBatis-Plus邏輯刪除和字段自動填充的實現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-08-08
  • 解決SpringMvc中普通類注入Service為null的問題

    解決SpringMvc中普通類注入Service為null的問題

    這篇文章主要介紹了解決SpringMvc中普通類注入Service為null的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • SpringBoot整合swagger的操作指南

    SpringBoot整合swagger的操作指南

    Swagger 是一個開源的框架,用于設(shè)計、構(gòu)建、文檔化和使用 RESTful 風(fēng)格的 Web 服務(wù),Spring Boot 是一個用于構(gòu)建獨立的、基于生產(chǎn)級別的 Spring 應(yīng)用程序的框架,本文講給大家介紹一下SpringBoot整合swagger的操作指南,需要的朋友可以參考下
    2023-09-09
  • Java訪問修飾符原理及代碼解析

    Java訪問修飾符原理及代碼解析

    這篇文章主要介紹了Java訪問修飾符原理及代碼解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-06-06
  • Window中安裝構(gòu)建神器Jenkins詳解

    Window中安裝構(gòu)建神器Jenkins詳解

    Jenkins是一款開源 CI&CD 軟件,用于自動化各種任務(wù),包括構(gòu)建、測試和部署軟件。支持各種運行方式,可通過系統(tǒng)包、Docker 或者通過一個獨立的 Java 程序。是解放人工集成部署的自動化構(gòu)建神器
    2021-07-07
  • Java實現(xiàn)多個文檔合并

    Java實現(xiàn)多個文檔合并

    這篇文章主要為大家詳細(xì)介紹了如何使用?Java?實現(xiàn)一個簡單且通用的文檔合并工具,主要針對文本文件的合并,感興趣的小伙伴可以參考一下
    2025-03-03
  • 2022年最新java?8?(?jdk1.8u321)安裝圖文教程

    2022年最新java?8?(?jdk1.8u321)安裝圖文教程

    這篇文章主要介紹了2022年最新java?8?(?jdk1.8u321)安裝圖文教程,截止2022年1月,官方出的jdk1.8目前已更新到8u321的版本,本文通過圖文并茂的形式給大家介紹安裝過程,需要的朋友可以參考下
    2022-08-08
  • Java工廠模式定義與用法實例分析

    Java工廠模式定義與用法實例分析

    這篇文章主要介紹了Java工廠模式定義與用法,結(jié)合具體實例形式分析了java工廠模式定義、使用相關(guān)操作技巧,并總結(jié)了類圖原理,需要的朋友可以參考下
    2019-07-07
  • MyBatis-Plus實現(xiàn)多數(shù)據(jù)源的示例代碼

    MyBatis-Plus實現(xiàn)多數(shù)據(jù)源的示例代碼

    這篇文章主要介紹了MyBatis-Plus實現(xiàn)多數(shù)據(jù)源的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java非法字符: ‘\ufeff‘問題及說明

    Java非法字符: ‘\ufeff‘問題及說明

    這篇文章主要介紹了Java非法字符: ‘\ufeff‘問題及說明,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論

南丹县| 梓潼县| 枣强县| 绥宁县| 丰县| 双城市| 沾化县| 太仆寺旗| 曲沃县| 商水县| 张掖市| 峨山| 洛浦县| 云林县| 海南省| 玉林市| 闸北区| 和龙市| 左权县| 渭南市| 临邑县| 张北县| 绍兴市| 义乌市| 凤城市| 松桃| 樟树市| 沛县| 平远县| 高青县| 武冈市| 杭州市| 金门县| 南江县| 西和县| 子长县| 饶河县| 赤壁市| 晋宁县| 赞皇县| 岐山县|