成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

SpringBoot 動(dòng)態(tài)代理|反射|注解(四)- 動(dòng)態(tài)代理對(duì)象注入到Spring容器

lingdududu / 2457人閱讀

摘要:上一篇?jiǎng)討B(tài)代理反射注解優(yōu)化代碼三注解本篇我們將實(shí)現(xiàn)通過(guò)代理生成的對(duì)象注入到容器中。單元測(cè)試優(yōu)化代碼待續(xù)參考文章

上一篇:SpringBoot 動(dòng)態(tài)代理|反射|注解|AOP 優(yōu)化代碼(三)-注解

本篇我們將實(shí)現(xiàn)通過(guò)代理生成的對(duì)象注入到spring容器中。
首先需要實(shí)現(xiàn)BeanDefinitionRegistryPostProcessor, ApplicationContextAware兩個(gè)接口,作用分別為:
ApplicationContextAware:可以獲得ApplicationContext對(duì)象,然后獲取Spring容器中的對(duì)象
BeanDefinitionRegistryPostProcessor+ FactoryBean:可以將我們自定義的bean注入到spring容器

@Slf4j
@Component
public class HandlerBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        /**
         * 獲取AutoImpl注解的接口,這些接口就需要通過(guò)動(dòng)態(tài)代理提供默認(rèn)實(shí)現(xiàn)
         */
        Set> classes = getAutoImplClasses();
        for (Class clazz : classes) {
            /**
             * 獲取繼承自HandlerRouter的接口的泛型的類型typeName,傳入到DynamicProxyBeanFactory
             * 以便傳入到DynamicProxyBeanFactory掃描typeName的實(shí)現(xiàn)類,然后按照f(shuō)eign和url兩種實(shí)現(xiàn)
             * 方式分類
             */

            Type[] types = clazz.getGenericInterfaces();
            ParameterizedType type = (ParameterizedType) types[0];
            String typeName = type.getActualTypeArguments()[0].getTypeName();

            /**
             * 通過(guò)FactoryBean注入到spring容器,HandlerInterfaceFactoryBean實(shí)現(xiàn)以下功能:
             * 1.調(diào)用動(dòng)態(tài)代理DynamicProxyBeanFactory提供HandlerRouter子接口的默認(rèn)實(shí)現(xiàn)
             * 2.將第一步的默認(rèn)實(shí)現(xiàn),注入到spring容器
             */

            HandlerRouterAutoImpl handlerRouterAutoImpl = clazz.getAnnotation(HandlerRouterAutoImpl.class);
            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
            definition.getPropertyValues().add("interfaceClass", clazz);
            definition.getPropertyValues().add("typeName", typeName);
            definition.getPropertyValues().add("context", applicationContext);
            definition.setBeanClass(HandlerInterfaceFactoryBean.class);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
            beanDefinitionRegistry.registerBeanDefinition(handlerRouterAutoImpl.name(), definition);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        log.info("------------------------>postProcessBeanFactory");
    }

    /**
     * 通過(guò)反射掃描出所有使用HandlerRouterAutoImpl的類
     * @return
     */
    private Set> getAutoImplClasses() {
        Reflections reflections = new Reflections(
                "io.ubt.iot.devicemanager.impl.handler.*",
                new TypeAnnotationsScanner(),
                new SubTypesScanner()
        );
        return reflections.getTypesAnnotatedWith(HandlerRouterAutoImpl.class);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
        log.info("------------------->setApplicationContext");
    }

    /**
     * 通過(guò)class獲取所有該類型的bean
     *
     * @param clazz
     * @return
     */
    private Map getBeans(Class clazz) {
        return applicationContext.getBeansOfType(clazz);
    }

    private String getYmlProperty(String propery) {
        return applicationContext.getEnvironment().getProperty(propery);
    }
}

HandlerInterfaceFactoryBean 通過(guò)動(dòng)態(tài)代理創(chuàng)建默認(rèn)實(shí)現(xiàn)類

@Slf4j
@Data
public class HandlerInterfaceFactoryBean implements FactoryBean {
    private Class interfaceClass;
    private String typeName;
    private ApplicationContext context;
    @Override
    public T getObject() throws Exception {
        Object object = DynamicProxyBeanFactory.newMapperProxy(typeName, context, interfaceClass);
        return (T) object;
    }

    @Override
    public Class getObjectType() {
        return interfaceClass;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}

DynamicProxyBeanFactory 最終實(shí)現(xiàn)

@Slf4j
public class DynamicProxyBeanFactory implements InvocationHandler {

    private String className;
    private ApplicationContext applicationContext;

    private Map clientMap = new HashMap<>(2);

    public DynamicProxyBeanFactory(String className, ApplicationContext applicationContext) {
        this.className = className;
        this.applicationContext = applicationContext;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (clientMap.size() == 0) {
            initClientMap();
        }
       
        Integer env = (Integer) args[0];
        return 1 == env.intValue() ? clientMap.get(ClientType.FEIGN) : clientMap.get(ClientType.URL);
    }

    private void initClientMap() throws ClassNotFoundException {
        //獲取classStr 接口的所有實(shí)現(xiàn)類
        Map classMap = applicationContext.getBeansOfType(Class.forName(className));
        log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap);

        for (Map.Entry entry : classMap.entrySet()) {
            //根據(jù)ApiClientType注解將實(shí)現(xiàn)類分為Feign和Url兩種類型
            ApiClient apiClient = entry.getValue().getClass().getAnnotation(ApiClient.class);
            if (apiClient == null) {
                continue;
            }
            clientMap.put(apiClient.type(), entry.getValue());
        }
        log.info("DynamicProxyBeanFactory clientMap:{}",clientMap);
    }


    public static  T newMapperProxy(String classStr,ApplicationContext applicationContext,Class mapperInterface) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        Class[] interfaces = new Class[]{mapperInterface};
        DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory(classStr,applicationContext);
        return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }
}

以上便是注解獲取目標(biāo)類,動(dòng)態(tài)代理提供默認(rèn)實(shí)現(xiàn),并注入到Spring容器的核心代碼。

單元測(cè)試
@Slf4j
@SpringBootTest
@RunWith(SpringRunner.class)
public class OptimizationTest {

    @Autowired
    @Qualifier("deviceHandlerRouter")
    private DeviceHandlerRouter deviceHandlerRouter;

    @Test
    public void dispatchApp() {

        DeviceHandler deviceHandlerFeignImpl = deviceHandlerRouter.getHandler(1, null);
        log.info("DeviceHandler-------------->{}",deviceHandlerFeignImpl);

        DeviceHandler deviceHandlerUrlImpl = deviceHandlerRouter.getHandler(2, null);
        log.info("DeviceHandler-------------->{}",deviceHandlerUrlImpl);
    }

   
}

Aop優(yōu)化代碼待續(xù)

參考文章https://blog.csdn.net/qq_2059...

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/75310.html

相關(guān)文章

  • SpringBoot 動(dòng)態(tài)代理|反射|注解|AOP 優(yōu)化代碼(三)-注解

    摘要:上一篇?jiǎng)討B(tài)代理反射注解優(yōu)化代碼二反射我們實(shí)現(xiàn)了通過(guò)反射完善找到目標(biāo)類,然后通過(guò)動(dòng)態(tài)代理提供默認(rèn)實(shí)現(xiàn),本篇我們將使用自定義注解來(lái)繼續(xù)優(yōu)化。下一篇?jiǎng)討B(tài)代理反射注解四動(dòng)態(tài)代理對(duì)象注入到容器 上一篇SpringBoot 動(dòng)態(tài)代理|反射|注解|AOP 優(yōu)化代碼(二)-反射 我們實(shí)現(xiàn)了通過(guò)反射完善找到目標(biāo)類,然后通過(guò)動(dòng)態(tài)代理提供默認(rèn)實(shí)現(xiàn),本篇我們將使用自定義注解來(lái)繼續(xù)優(yōu)化。 創(chuàng)建注解 1.創(chuàng)建枚舉...

    Charles 評(píng)論0 收藏0
  • SpringBoot 動(dòng)態(tài)代理|反射|注解|AOP 優(yōu)化代碼(二)-反射

    摘要:動(dòng)態(tài)代理反射注解優(yōu)化代碼一動(dòng)態(tài)代理提供接口默認(rèn)實(shí)現(xiàn)我們拋出問(wèn)題,并且提出解決問(wèn)題的第一步的方法。重寫動(dòng)態(tài)代理類,實(shí)現(xiàn)通過(guò)的查找出傳入的所有泛型的實(shí)現(xiàn)下一篇?jiǎng)討B(tài)代理反射注解優(yōu)化代碼三注解 SpringBoot 動(dòng)態(tài)代理|反射|注解|AOP 優(yōu)化代碼(一)-動(dòng)態(tài)代理提供接口默認(rèn)實(shí)現(xiàn) 我們拋出問(wèn)題,并且提出解決問(wèn)題的第一步的方法。下面我們繼續(xù)深入,動(dòng)態(tài)代理和反射繼續(xù)解決我們的問(wèn)題。 改動(dòng)代...

    spacewander 評(píng)論0 收藏0
  • spring 入門 2 自動(dòng)裝配和aop

    摘要:使用注解配置一步驟為主配置文件引入新的命名空間約束導(dǎo)入約束開(kāi)啟使用注解代理配置文件在中指定掃描包下所有類的注解掃描時(shí)會(huì)掃描指定包下的所有子孫包在類中使用注解完成配置等二將對(duì)象注冊(cè)到容器將注冊(cè)到容器中,相當(dāng)于層層層三修改對(duì)象的作用范 使用注解配置spring 一、步驟 1.為主配置文件引入新的命名空間(約束) 導(dǎo)入spring-context-4.2.xsd schema約束 show...

    JasinYip 評(píng)論0 收藏0
  • Spring入門IOC和AOP學(xué)習(xí)筆記

    摘要:入門和學(xué)習(xí)筆記概述框架的核心有兩個(gè)容器作為超級(jí)大工廠,負(fù)責(zé)管理創(chuàng)建所有的對(duì)象,這些對(duì)象被稱為。中的一些術(shù)語(yǔ)切面切面組織多個(gè),放在切面中定義。 Spring入門IOC和AOP學(xué)習(xí)筆記 概述 Spring框架的核心有兩個(gè): Spring容器作為超級(jí)大工廠,負(fù)責(zé)管理、創(chuàng)建所有的Java對(duì)象,這些Java對(duì)象被稱為Bean。 Spring容器管理容器中Bean之間的依賴關(guān)系,使用一種叫做依賴...

    wenyiweb 評(píng)論0 收藏0
  • Spring自定義注解不生效原因解析及解決方法

    摘要:自定義注解不生效原因解析及解決方法背景項(xiàng)目中,自己基于實(shí)現(xiàn)了一套緩存注解。但是最近出現(xiàn)一種情況緩存竟然沒(méi)有生效,大量請(qǐng)求被擊穿到層,導(dǎo)致壓力過(guò)大。至此,問(wèn)題得到解決。 自定義注解不生效原因解析及解決方法 背景: 項(xiàng)目中,自己基于spring AOP實(shí)現(xiàn)了一套java緩存注解。但是最近出現(xiàn)一種情況:緩存竟然沒(méi)有生效,大量請(qǐng)求被擊穿到db層,導(dǎo)致db壓力過(guò)大?,F(xiàn)在我們看一下具體代碼情形(代...

    xbynet 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<