摘要:上一篇動態(tài)代理反射注解優(yōu)化代碼三注解本篇我們將實現(xiàn)通過代理生成的對象注入到容器中。單元測試優(yōu)化代碼待續(xù)參考文章
上一篇:SpringBoot 動態(tài)代理|反射|注解|AOP 優(yōu)化代碼(三)-注解
本篇我們將實現(xiàn)通過代理生成的對象注入到spring容器中。
首先需要實現(xiàn)BeanDefinitionRegistryPostProcessor, ApplicationContextAware兩個接口,作用分別為:
ApplicationContextAware:可以獲得ApplicationContext對象,然后獲取Spring容器中的對象
BeanDefinitionRegistryPostProcessor+ FactoryBean:可以將我們自定義的bean注入到spring容器
@Slf4j @Component public class HandlerBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { private ApplicationContext applicationContext; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { /** * 獲取AutoImpl注解的接口,這些接口就需要通過動態(tài)代理提供默認實現(xiàn) */ Set> classes = getAutoImplClasses(); for (Class> clazz : classes) { /** * 獲取繼承自HandlerRouter的接口的泛型的類型typeName,傳入到DynamicProxyBeanFactory * 以便傳入到DynamicProxyBeanFactory掃描typeName的實現(xiàn)類,然后按照feign和url兩種實現(xiàn) * 方式分類 */ Type[] types = clazz.getGenericInterfaces(); ParameterizedType type = (ParameterizedType) types[0]; String typeName = type.getActualTypeArguments()[0].getTypeName(); /** * 通過FactoryBean注入到spring容器,HandlerInterfaceFactoryBean實現(xiàn)以下功能: * 1.調(diào)用動態(tài)代理DynamicProxyBeanFactory提供HandlerRouter子接口的默認實現(xiàn) * 2.將第一步的默認實現(xiàn),注入到spring容器 */ HandlerRouterAutoImpl handlerRouterAutoImpl = clazz.getAnnotation(HandlerRouterAutoImpl.class); BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz); GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition(); definition.getPropertyValues().add("interfaceClass", clazz); definition.getPropertyValues().add("typeName", typeName); definition.getPropertyValues().add("context", applicationContext); definition.setBeanClass(HandlerInterfaceFactoryBean.class); definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); beanDefinitionRegistry.registerBeanDefinition(handlerRouterAutoImpl.name(), definition); } } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { log.info("------------------------>postProcessBeanFactory"); } /** * 通過反射掃描出所有使用HandlerRouterAutoImpl的類 * @return */ private Set > getAutoImplClasses() { Reflections reflections = new Reflections( "io.ubt.iot.devicemanager.impl.handler.*", new TypeAnnotationsScanner(), new SubTypesScanner() ); return reflections.getTypesAnnotatedWith(HandlerRouterAutoImpl.class); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; log.info("------------------->setApplicationContext"); } /** * 通過class獲取所有該類型的bean * * @param clazz * @return */ private Map getBeans(Class clazz) { return applicationContext.getBeansOfType(clazz); } private String getYmlProperty(String propery) { return applicationContext.getEnvironment().getProperty(propery); } }
HandlerInterfaceFactoryBean 通過動態(tài)代理創(chuàng)建默認實現(xiàn)類
@Slf4j @Data public class HandlerInterfaceFactoryBeanimplements FactoryBean { private Class interfaceClass; private String typeName; private ApplicationContext context; @Override public T getObject() throws Exception { Object object = DynamicProxyBeanFactory.newMapperProxy(typeName, context, interfaceClass); return (T) object; } @Override public Class> getObjectType() { return interfaceClass; } @Override public boolean isSingleton() { return true; } }
DynamicProxyBeanFactory 最終實現(xiàn)
@Slf4j public class DynamicProxyBeanFactory implements InvocationHandler { private String className; private ApplicationContext applicationContext; private MapclientMap = new HashMap<>(2); public DynamicProxyBeanFactory(String className, ApplicationContext applicationContext) { this.className = className; this.applicationContext = applicationContext; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (clientMap.size() == 0) { initClientMap(); } 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 = applicationContext.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 classStr,ApplicationContext applicationContext,Class mapperInterface) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class>[] interfaces = new Class[]{mapperInterface}; DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory(classStr,applicationContext); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); } }
以上便是注解獲取目標類,動態(tài)代理提供默認實現(xiàn),并注入到Spring容器的核心代碼。
單元測試@Slf4j @SpringBootTest @RunWith(SpringRunner.class) public class OptimizationTest { @Autowired @Qualifier("deviceHandlerRouter") private DeviceHandlerRouter deviceHandlerRouter; @Test public void dispatchApp() { DeviceHandler deviceHandlerFeignImpl = deviceHandlerRouter.getHandler(1, null); log.info("DeviceHandler-------------->{}",deviceHandlerFeignImpl); DeviceHandler deviceHandlerUrlImpl = deviceHandlerRouter.getHandler(2, null); log.info("DeviceHandler-------------->{}",deviceHandlerUrlImpl); } }
Aop優(yōu)化代碼待續(xù)
參考文章https://blog.csdn.net/qq_2059...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/75310.html
摘要:上一篇動態(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)建枚舉...
摘要:動態(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ù)解決我們的問題。 改動代...
摘要:使用注解配置一步驟為主配置文件引入新的命名空間約束導(dǎo)入約束開啟使用注解代理配置文件在中指定掃描包下所有類的注解掃描時會掃描指定包下的所有子孫包在類中使用注解完成配置等二將對象注冊到容器將注冊到容器中,相當于層層層三修改對象的作用范 使用注解配置spring 一、步驟 1.為主配置文件引入新的命名空間(約束) 導(dǎo)入spring-context-4.2.xsd schema約束 show...
摘要:入門和學習筆記概述框架的核心有兩個容器作為超級大工廠,負責管理創(chuàng)建所有的對象,這些對象被稱為。中的一些術(shù)語切面切面組織多個,放在切面中定義。 Spring入門IOC和AOP學習筆記 概述 Spring框架的核心有兩個: Spring容器作為超級大工廠,負責管理、創(chuàng)建所有的Java對象,這些Java對象被稱為Bean。 Spring容器管理容器中Bean之間的依賴關(guān)系,使用一種叫做依賴...
摘要:自定義注解不生效原因解析及解決方法背景項目中,自己基于實現(xiàn)了一套緩存注解。但是最近出現(xiàn)一種情況緩存竟然沒有生效,大量請求被擊穿到層,導(dǎo)致壓力過大。至此,問題得到解決。 自定義注解不生效原因解析及解決方法 背景: 項目中,自己基于spring AOP實現(xiàn)了一套java緩存注解。但是最近出現(xiàn)一種情況:緩存竟然沒有生效,大量請求被擊穿到db層,導(dǎo)致db壓力過大。現(xiàn)在我們看一下具體代碼情形(代...
閱讀 1525·2023-04-25 17:41
閱讀 3045·2021-11-22 15:08
閱讀 846·2021-09-29 09:35
閱讀 1610·2021-09-27 13:35
閱讀 3327·2021-08-31 09:44
閱讀 2720·2019-08-30 13:20
閱讀 1943·2019-08-30 13:00
閱讀 2563·2019-08-26 12:12