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

6次阅读

共计 3694 个字符,预计需要花费 10 分钟才能阅读完成。

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

改动代码结构

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

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

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

public interface DeviceHandlerRouter extends HandlerRouter<DeviceHandler> {}

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

DeviceHandlerRouter deviceHandlerRouter = ...
deviceHandlerRouter.getHandler(...). remoteAddBatch(...)

反射 + 动态代理

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

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

首先加入下面的依赖

        <dependency>
            <groupId>org.reflections</groupId>
            <artifactId>reflections</artifactId>
            <version>0.9.10</version>
        </dependency>
/**
 * 通过反射扫描出所有 HandlerRouter 的子类
 * @return
 */
private Set<Class<?>> getHandlerRouterClasses() {
        Reflections reflections = new Reflections(
                "package.name.*",
                new TypeAnnotationsScanner(),// 注解扫描,本节用不到
                new SubTypesScanner());
        return reflections.getSubTypesOf(HandlerRouter.class);
}
Set<Class<?>> 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> 中的 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<String, ?> 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<String,?> classMap =SpringUtil.getBeans(Class.forName(className));
        log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap);
        // 这里先随便返回一个
        return classMap.get("deviceHandlerUrlImpl");}


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

调用:

Set<Class<?>> 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> 中的 DeviceHandler.class
    //typeName 对应 DeviceHandlerRouter extends HandlerRouter<DeviceHandler> 中的 DeviceHandler.class
    //typeName 对应 DeviceHandlerRouter extends HandlerRouter<DeviceHandler> 中的 DeviceHandler.class
    
    String typeName = type.getActualTypeArguments()[0].getTypeName();
    
    
    DeviceHandler deviceHandler = DynamicProxyBeanFactory.newMapperProxy(typeName,clazz);
}

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

正文完
 0