SpringBoot 動態代理|反射|註解|AOP 優化代碼(三)-註解

上一篇SpringBoot 動態代理|反射|註解|AOP 優化代碼(二)-反射spring

咱們實現了經過反射完善找到目標類,而後經過動態代理提供默認實現,本篇咱們將使用自定義註解來繼續優化。segmentfault

建立註解

1.建立枚舉 ClientType,用來標明Handler的實現方式api

public enum ClientType {
    FEIGN,URL
}

2.建立註解ApiClient,用來標明Handler的實現方式app

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

3.建立HandlerRouterAutoImpl註解,來標記該HandlerRouter是否經過代理提供默認實現ide

@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 添加註解標明具體的實現方式this

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

6.經過註解掃描目標類url

掃描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方式時根據傳入的環境值,返回不一樣實現方式的實例。rest

@Slf4j
public 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容器

相關文章
相關標籤/搜索