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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。