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

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


liumang
343 声望36 粉丝

一直在思考怎么结合自己擅长的知识做些什么。现在有了好主意坚持一年,看看会有什么改变,有什么美好的事情发生。