SpringBoot动态代理|反射|注释| AOP优化代码(1)

优采云 发布时间: 2020-08-06 17:18

  I. 背景

  在项目中,您需要调用一个外部接口,因为您需要在不同的环境(生产,测试,开发)中调用相同的接口(例如: 将相同的APP发送到生产,测试和测试中的设备)开发环境).

  1.生产环境由SpringCloud注册中心,通过Feign调用,

2.其它环境直接通过OKHttp直接通过Url调用。

  因此,有必要根据传入环境选择不同的调用方法.

  优化前的代码结构

  以下是添加和删除设备接口的示例(都很简单,它不代表真实的业务代码):

  public interface DeviceHandler {

void remoteAddBatch(RemoteAddDeviceParam remoteAddDeviceParam, Integer envValue);

void remoteDeleteBatch(Integer envValue, List snsList);

}

  好的实现方式:

  @Component

@Slf4j

public class DeviceHandlerFeignImpl implements DeviceHandler {

@Autowired

private DeviceFeignClient deviceFeignClient;

@Override

public void remoteAddBatch(RemoteAddDeviceParam remoteAddDeviceParam, Integer envValue) {

RestResult restResult = deviceFeignClient.create(remoteAddDeviceParam);

...

}

@Override

public void remoteDeleteBatch(Integer envValue, List snsList) {

RestResult restResult = deviceFeignClient.deleteBySnList(snsList);

...

}

}

  网址模式实现

  @Component

@Slf4j

public class DeviceHandlerUrlImpl implements DeviceHandler {

@Override

public void remoteAddBatch(RemoteAddDeviceParam remoteAddDeviceParam, Integer envValue) {

String url = getAddUrlByEnvValue(envValue);

String response = OkHttpUtils.httpPostSyn(url, JSON.toJSONString(snsList), false);

RestResult restResult = JSON.parseObject(response, RestResult.class);

...

}

@Override

public void remoteDeleteBatch(Integer envValue, List snsList) {

String url = getDelUrlByEnvValue(envValue);

String response = OkHttpUtils.httpPostSyn(url, JSON.toJSONString(snsList), false);

RestResult restResult = JSON.parseObject(response, RestResult.class);

...

}

}

  DeviceHandlerRouter扮演路由的角色(实际上类似于代理),选择要调用的实现,并将DeviceHandlerRouter公开给上层服务.

  @Component

public class DeviceHandlerRouter implements DeviceHandler {

...

@Autowired

private DeviceHandlerUrlImpl deviceHandlerUrlImpl;

@Autowired

private DeviceHandlerUrlImpl deviceHandlerUrlImpl;

@Override

public void remoteAddBatch(RemoteAddDeviceParam remoteAddDeviceParam, Integer envValue) {

getDeviceHandler(envValue).remoteAddBatch(remoteAddDeviceParam,envValue);

}

@Override

public void remoteDeleteBatch(Integer envValue, List snsList) {

getDeviceHandler(envValue).remoteDeleteBatch(envValue,snsList);

}

private DeviceHandler getDeviceHandler(Integer envValue) {

//根据传入的环境返回DeviceHandlerUrlImpl 或 DeviceHandlerUrlImpl

}

}

  上层服务调用DeviceHandlerRouter来添加和删除设备.

  有问题

  如果添加一个常量接口调用,则需要实现xxxRouter,但是代码基本相同. 有什么方法可以在不编写代码的情况下提供默认实现?

  动态代理提供默认实现

  @Slf4j

public class DynamicProxyBeanFactory implements InvocationHandler {

@Override

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

//各位客官别急,这里只是简单打印一下,真正的代码在下一篇

log.info("DynamicProxyBeanFactory------------------>invoke")

//正儿八经的随便创建一个DeviceHandlerUrlImpl

return new DeviceHandlerUrlImpl();

}

public static T newMapperProxy(Class mapperInterface) {

ClassLoader classLoader = mapperInterface.getClassLoader();

Class[] interfaces = new Class[]{mapperInterface};

DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory();

return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);

}

}

  致电:

  DeviceHandler deviceHandler = DynamicProxyBeanFactory.newMapperProxy(DeviceHandler.class);

  deviceHandler.remoteAddBatch(...);

  参考链接: 动态代理提供接口的默认实现

  摘要

  以上我们只是抛出了实际开发中遇到的问题,并找到了解决问题的第一种方法. 当然,动态代理提供的接口的默认实现只是一个演示,而没有实际内容.

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线