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

我们实现了通过反射完善找到目标类,然后通过动态代理提供默认实现,本篇我们将使用自定义注解来继续优化。

创建注解

1.创建枚举 ClientType,用来标明Handler的实现方式

public enum ClientType {    FEIGN,URL}

2.创建注解ApiClient,用来标明Handler的实现方式

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface ApiClient {    ClientType type();}

3.创建HandlerRouterAutoImpl注解,来标记该HandlerRouter是否通过代理提供默认实现

@Documented@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)public @interface HandlerRouterAutoImpl {   /**    * 在spring容器中对应的名称    * @return    */   String name();}

4.DeviceHandlerRouter添加注解,以动态代理提供默认实现

@HandlerRouterAutoImpl(name = "deviceHandlerRouter")public interface DeviceHandlerRouter extends HandlerRouter<DeviceHandler> {}

5.DeviceHandlerFeignImpl、DeviceHandlerUrlImpl 添加注解标明具体的实现方式

@ApiClient(type = ClientType.FEIGN)@Component@Slf4jpublic 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<String> snsList) {           RestResult restResult = deviceFeignClient.deleteBySnList(snsList);              ...     }     }
@ApiClient(type = ClientType.URL)@Component@Slf4jpublic 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<String> snsList) {        String url = getDelUrlByEnvValue(envValue);        String response = OkHttpUtils.httpPostSyn(url, JSON.toJSONString(snsList), false);        RestResult restResult = JSON.parseObject(response, RestResult.class);        ...    }}

6.通过注解扫描目标类

扫描HandlerRouterAutoImpl注解的类,通过动态代理提供默认的实现

    /**     * 通过反射扫描出所有使用注解HandlerRouterAutoImpl的类     * @return     */    private Set<Class<?>> getAutoImplClasses() {        Reflections reflections = new Reflections(                "io.ubt.iot.devicemanager.impl.handler.*",                new TypeAnnotationsScanner(),                new SubTypesScanner()        );        return reflections.getTypesAnnotatedWith(HandlerRouterAutoImpl.class);    }

动态代理类中,获取业务接口的实现类,并获取ApiClient注解,然后分类,保存到Map中。以在调用getHandler方式时根据传入的环境值,返回不同实现方式的实例。

@Slf4jpublic class DynamicProxyBeanFactory implements InvocationHandler {    private String className;    private Map<ClientType, Object> clientMap = new HashMap<>(2);    public DynamicProxyBeanFactory(String className) {        this.className = className;    }    @Override    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {        //获取过一次后不再获取        if (clientMap.size() == 0) {            initClientMap();        }                //如果传入的参数是1,就返回通过Feign方式实现的类 (该逻辑只是用来举例)        Integer env = (Integer) args[0];        return 1 == env.intValue() ? clientMap.get(ClientType.FEIGN) : clientMap.get(ClientType.URL);    }    private void initClientMap() throws ClassNotFoundException {        //获取classStr 接口的所有实现类        Map<String,?> classMap =SpringUtil.getBeansOfType(Class.forName(className));        log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap);        for (Map.Entry<String,?> entry : classMap.entrySet()) {            //根据ApiClientType注解将实现类分为Feign和Url两种类型            ApiClient apiClient = entry.getValue().getClass().getAnnotation(ApiClient.class);            if (apiClient == null) {                continue;            }            clientMap.put(apiClient.type(), entry.getValue());        }        log.info("DynamicProxyBeanFactory clientMap:{}",clientMap);    }    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);    }}

以上我们通过注解、动态代理、反射就实现了通过注解,找到需要提供默认实现的HandlerRouter子类,并通过动态代理提供默认实现。
还有一个问题:通过代理生成的对象,该怎么管理,我们并不想通过代码,手动管理。如果能把动态代理生成的对象交给spring容器管理,其它代码直接自动注入就可以了。

下一篇:SpringBoot 动态代理|反射|注解(四)- 动态代理对象注入到Spring容器