摘要:上一篇動態(tài)代理反射注解優(yōu)化代碼二反射我們實現(xiàn)了通過反射完善找到目標類,然后通過動態(tài)代理提供默認實現(xiàn),本篇我們將使用自定義注解來繼續(xù)優(yōu)化。下一篇動態(tài)代理反射注解四動態(tài)代理對象注入到容器
上一篇SpringBoot 動態(tài)代理|反射|注解|AOP 優(yōu)化代碼(二)-反射
我們實現(xiàn)了通過反射完善找到目標類,然后通過動態(tài)代理提供默認實現(xiàn),本篇我們將使用自定義注解來繼續(xù)優(yōu)化。
創(chuàng)建注解1.創(chuàng)建枚舉 ClientType,用來標明Handler的實現(xiàn)方式
public enum ClientType { FEIGN,URL }
2.創(chuàng)建注解ApiClient,用來標明Handler的實現(xiàn)方式
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface ApiClient { ClientType type(); }
3.創(chuàng)建HandlerRouterAutoImpl注解,來標記該HandlerRouter是否通過代理提供默認實現(xiàn)
@Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface HandlerRouterAutoImpl { /** * 在spring容器中對應的名稱 * @return */ String name(); }
4.DeviceHandlerRouter添加注解,以動態(tài)代理提供默認實現(xiàn)
@HandlerRouterAutoImpl(name = "deviceHandlerRouter") public interface DeviceHandlerRouter extends HandlerRouter{ }
5.DeviceHandlerFeignImpl、DeviceHandlerUrlImpl 添加注解標明具體的實現(xiàn)方式
@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, ListsnsList) { 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, ListsnsList) { String url = getDelUrlByEnvValue(envValue); String response = OkHttpUtils.httpPostSyn(url, JSON.toJSONString(snsList), false); RestResult restResult = JSON.parseObject(response, RestResult.class); ... } }
6.通過注解掃描目標類
掃描HandlerRouterAutoImpl注解的類,通過動態(tài)代理提供默認的實現(xiàn)
/** * 通過反射掃描出所有使用注解HandlerRouterAutoImpl的類 * @return */ private Set> getAutoImplClasses() { Reflections reflections = new Reflections( "io.ubt.iot.devicemanager.impl.handler.*", new TypeAnnotationsScanner(), new SubTypesScanner() ); return reflections.getTypesAnnotatedWith(HandlerRouterAutoImpl.class); }
動態(tài)代理類中,獲取業(yè)務接口的實現(xiàn)類,并獲取ApiClient注解,然后分類,保存到Map中。以在調用getHandler方式時根據(jù)傳入的環(huán)境值,返回不同實現(xiàn)方式的實例。
@Slf4j public class DynamicProxyBeanFactory implements InvocationHandler { private String className; private MapclientMap = 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(); } //如果傳入的參數(shù)是1,就返回通過Feign方式實現(xiàn)的類 (該邏輯只是用來舉例) Integer env = (Integer) args[0]; return 1 == env.intValue() ? clientMap.get(ClientType.FEIGN) : clientMap.get(ClientType.URL); } private void initClientMap() throws ClassNotFoundException { //獲取classStr 接口的所有實現(xiàn)類 Map classMap =SpringUtil.getBeansOfType(Class.forName(className)); log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap); for (Map.Entry entry : classMap.entrySet()) { //根據(jù)ApiClientType注解將實現(xiàn)類分為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 newMapperProxy(String typeName,Class mapperInterface) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class>[] interfaces = new Class[]{mapperInterface}; DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory(typeName); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); } }
以上我們通過注解、動態(tài)代理、反射就實現(xiàn)了通過注解,找到需要提供默認實現(xiàn)的HandlerRouter子類,并通過動態(tài)代理提供默認實現(xiàn)。
還有一個問題:通過代理生成的對象,該怎么管理,我們并不想通過代碼,手動管理。如果能把動態(tài)代理生成的對象交給spring容器管理,其它代碼直接自動注入就可以了。
下一篇:SpringBoot 動態(tài)代理|反射|注解(四)- 動態(tài)代理對象注入到Spring容器
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://www.ezyhdfw.cn/yun/75283.html
摘要:動態(tài)代理反射注解優(yōu)化代碼一動態(tài)代理提供接口默認實現(xiàn)我們拋出問題,并且提出解決問題的第一步的方法。重寫動態(tài)代理類,實現(xiàn)通過的查找出傳入的所有泛型的實現(xiàn)下一篇動態(tài)代理反射注解優(yōu)化代碼三注解 SpringBoot 動態(tài)代理|反射|注解|AOP 優(yōu)化代碼(一)-動態(tài)代理提供接口默認實現(xiàn) 我們拋出問題,并且提出解決問題的第一步的方法。下面我們繼續(xù)深入,動態(tài)代理和反射繼續(xù)解決我們的問題。 改動代...
摘要:生產環(huán)境由注冊中心,通過調用,其它環(huán)境直接通過直接通過調用。當然動態(tài)代理提供接口的默認實現(xiàn)只是演示,并沒有什么實際內容。下一篇動態(tài)代理反射注解優(yōu)化代碼二反射 一、背景 在項目中需要調用外部接口,由于需要調用不同環(huán)境(生產、測試、開發(fā))的相同接口(例如:向生、測試、開發(fā)環(huán)境的設備下發(fā)同一個APP)。 1.生產環(huán)境由SpringCloud注冊中心,通過Feign調用, 2.其它環(huán)境直接通過...
摘要:上一篇動態(tài)代理反射注解優(yōu)化代碼三注解本篇我們將實現(xiàn)通過代理生成的對象注入到容器中。單元測試優(yōu)化代碼待續(xù)參考文章 上一篇:SpringBoot 動態(tài)代理|反射|注解|AOP 優(yōu)化代碼(三)-注解 本篇我們將實現(xiàn)通過代理生成的對象注入到spring容器中。首先需要實現(xiàn)BeanDefinitionRegistryPostProcessor, ApplicationContextAware兩個...
摘要:又是什么其實就是一種實現(xiàn)動態(tài)代理的技術,利用了開源包,先將代理對象類的文件加載進來,之后通過修改其字節(jié)碼并且生成子類。 在實際研發(fā)中,Spring是我們經(jīng)常會使用的框架,畢竟它們太火了,也因此Spring相關的知識點也是面試必問點,今天我們就大話Aop。特地在周末推文,因為該篇文章閱讀起來還是比較輕松詼諧的,當然了,更主要的是周末的我也在充電學習,希望有追求的朋友們也盡量不要放過周末時...
閱讀 2886·2023-04-25 23:08
閱讀 1700·2021-11-23 09:51
閱讀 1698·2021-10-27 14:18
閱讀 3175·2019-08-29 13:25
閱讀 2896·2019-08-29 13:14
閱讀 3039·2019-08-26 18:36
閱讀 2261·2019-08-26 12:11
閱讀 875·2019-08-26 11:29