资讯专栏INFORMATION COLUMN

SpringBoot 动态代理|反射|注解|AOP 优化代码(二)-反射

spacewander / 936人阅读

摘要:动态代理反射注解优化代码一动态代理提供接口默认实现我们抛出问题,并且提出解决问题的第一步的方法。重写动态代理类,实现通过的查找出传入的所有泛型的实现下一篇动态代理反射注解优化代码三注解

SpringBoot 动态代理|反射|注解|AOP 优化代码(一)-动态代理提供接口默认实现 我们抛出问题,并且提出解决问题的第一步的方法。下面我们继续深入,动态代理和反射继续解决我们的问题。

改动代码结构

新增一个HandlerRougter接口,其目的就是替代上一篇的DeviceHandlerRouter

public interface HandlerRouter {
    T getHandler(Integer env,Object... args);
}

其中T是具体的业务接口。下面实现DeviceHandler的HandlerRouter:

public interface DeviceHandlerRouter extends HandlerRouter {
}

那么上层代码的调用方式将会类似下面的代码:

DeviceHandlerRouter deviceHandlerRouter = ...
deviceHandlerRouter.getHandler(...). remoteAddBatch(...)
反射+动态代理

前面说过,每增加一种接口调用,就需要重新实现xxxHandlerRouter,那么下面我们通过动态代理和反射提供DeviceHandler的默认实现。

1.通过反射获取HandlerRouter的子接口和泛型对应的类

首先加入下面的依赖

        
            org.reflections
            reflections
            0.9.10
        
/**
 * 通过反射扫描出所有HandlerRouter的子类
 * @return
 */
private Set> getHandlerRouterClasses() {
        Reflections reflections = new Reflections(
                "package.name.*",
                new TypeAnnotationsScanner(),//注解扫描,本节用不到
                new SubTypesScanner()
        );
        return reflections.getSubTypesOf(HandlerRouter.class);
}
Set> classes = getHandlerRouterClasses();
//获取HandlerRouter的子接口的泛型Class 例如:DeviceHandlerRouter接口的DeviceHandler
for (Class clazz : classes) {
    //clazz 对应DeviceHandlerRouter.class
    Type[] types = clazz.getGenericInterfaces();
    ParameterizedType type = (ParameterizedType) types[0];
    
    //typeName对应DeviceHandlerRouter extends HandlerRouter 中的DeviceHandler.class
    String typeName = type.getActualTypeArguments()[0].getTypeName();
}

2.SpringBoot ApplicationContext 获取注入的bean

修改上一篇中实现的动态代理类,我们想要实现:“能够根据传入的泛型的Class 获取到Spring容器中该类型的所有bean”,因此我们就需要传入ApplicationContext。那就需要实现ApplicationContextAware接口,下面的代码来自网络。

@Component
public class SpringUtil implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        SpringUtil.applicationContext = applicationContext;
    }

    public static ApplicationContext getApplicationContext() {
        return applicationContext;
    }


    /**
     * 通过class获取所有该类型的bean
     * @param clazz
     * @return
     */
    public static Map getBeans(Class clazz) {
        return getApplicationContext().getBeansOfType(clazz);
    }
}

3.重新实现动态代理类

@Slf4j
public class DynamicProxyBeanFactory implements InvocationHandler {
    private String className;
    
    public DynamicProxyBeanFactory(String className) {
        this.className = className;
    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //获取实现className类的所有bean
        Map classMap =SpringUtil.getBeans(Class.forName(className));
        log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap);
        //这里先随便返回一个
        return classMap.get("deviceHandlerUrlImpl");
    }


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

调用:

Set> classes = getHandlerRouterClasses();
//获取HandlerRouter的子接口的泛型Class 例如:DeviceHandlerRouter接口的DeviceHandler
for (Class clazz : classes) {
    //clazz 对应DeviceHandlerRouter.class
    //clazz 对应DeviceHandlerRouter.class
    //clazz 对应DeviceHandlerRouter.class
    
    Type[] types = clazz.getGenericInterfaces();
    ParameterizedType type = (ParameterizedType) types[0];
    
    //typeName对应DeviceHandlerRouter extends HandlerRouter 中的DeviceHandler.class
    //typeName对应DeviceHandlerRouter extends HandlerRouter 中的DeviceHandler.class
    //typeName对应DeviceHandlerRouter extends HandlerRouter 中的DeviceHandler.class
    
    String typeName = type.getActualTypeArguments()[0].getTypeName();
    
    
    DeviceHandler deviceHandler = DynamicProxyBeanFactory.newMapperProxy(typeName,clazz);
}

总结:这篇文章我们
1.通过反射获取了HandlerRouter的所有子接口(这里是DeviceHandlerRouter),以及子接口对应的泛型。
2.重写动态代理类,实现通过Spring的ApplicationContext查找出传入的所有泛型的实现bean

下一篇:SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75288.html

相关文章

  • SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解

    摘要:上一篇动态代理反射注解优化代码二反射我们实现了通过反射完善找到目标类,然后通过动态代理提供默认实现,本篇我们将使用自定义注解来继续优化。下一篇动态代理反射注解四动态代理对象注入到容器 上一篇SpringBoot 动态代理|反射|注解|AOP 优化代码(二)-反射 我们实现了通过反射完善找到目标类,然后通过动态代理提供默认实现,本篇我们将使用自定义注解来继续优化。 创建注解 1.创建枚举...

    Charles 评论0 收藏0
  • SpringBoot 动态代理|反射|注解|AOP 优化代码(一)-动态代理提供接口默认实现

    摘要:生产环境由注册中心,通过调用,其它环境直接通过直接通过调用。当然动态代理提供接口的默认实现只是演示,并没有什么实际内容。下一篇动态代理反射注解优化代码二反射 一、背景 在项目中需要调用外部接口,由于需要调用不同环境(生产、测试、开发)的相同接口(例如:向生、测试、开发环境的设备下发同一个APP)。 1.生产环境由SpringCloud注册中心,通过Feign调用, 2.其它环境直接通过...

    mj 评论0 收藏0
  • SpringBoot 动态代理|反射|注解(四)- 动态代理对象注入到Spring容器

    摘要:上一篇动态代理反射注解优化代码三注解本篇我们将实现通过代理生成的对象注入到容器中。单元测试优化代码待续参考文章 上一篇:SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解 本篇我们将实现通过代理生成的对象注入到spring容器中。首先需要实现BeanDefinitionRegistryPostProcessor, ApplicationContextAware两个...

    lingdududu 评论0 收藏0
  • 【好好面试】学完Aop,连动态代理的原理都不懂?

    摘要:总结动态代理的相关原理已经讲解完毕,接下来让我们回答以下几个思考题。 【干货点】 此处是【好好面试】系列文的第12篇文章。文章目标主要是通过原理剖析的方式解答Aop动态代理的面试热点问题,通过一步步提出问题和了解原理的方式,我们可以记得更深更牢,进而解决被面试官卡住喉咙的情况。问题如下 SpringBoot默认代理类型是什么 为什么不用静态代理 JDK动态代理原理 CGLIB动态代理...

    Keven 评论0 收藏0

发表评论

0条评论

spacewander

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<