上一篇:SpringBoot 動態代理|反射|註解|AOP 優化代碼(三)-註解spring
本篇咱們將實現經過代理生成的對象注入到spring容器中。
首先須要實現BeanDefinitionRegistryPostProcessor, ApplicationContextAware兩個接口,做用分別爲:
ApplicationContextAware:能夠得到ApplicationContext對象,而後獲取Spring容器中的對象
BeanDefinitionRegistryPostProcessor+ FactoryBean:能夠將咱們自定義的bean注入到spring容器segmentfault
@Slf4j @Component public class HandlerBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware { private ApplicationContext applicationContext; @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { /** * 獲取AutoImpl註解的接口,這些接口就須要經過動態代理提供默認實現 */ Set<Class<?>> classes = getAutoImplClasses(); for (Class<?> clazz : classes) { /** * 獲取繼承自HandlerRouter的接口的泛型的類型typeName,傳入到DynamicProxyBeanFactory * 以便傳入到DynamicProxyBeanFactory掃描typeName的實現類,而後按照feign和url兩種實現 * 方式分類 */ Type[] types = clazz.getGenericInterfaces(); ParameterizedType type = (ParameterizedType) types[0]; String typeName = type.getActualTypeArguments()[0].getTypeName(); /** * 經過FactoryBean注入到spring容器,HandlerInterfaceFactoryBean實現如下功能: * 1.調用動態代理DynamicProxyBeanFactory提供HandlerRouter子接口的默認實現 * 2.將第一步的默認實現,注入到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<Class<?>> 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<String, T> getBeans(Class<T> clazz) { return applicationContext.getBeansOfType(clazz); } private String getYmlProperty(String propery) { return applicationContext.getEnvironment().getProperty(propery); } }
HandlerInterfaceFactoryBean 經過動態代理建立默認實現類api
@Slf4j @Data public class HandlerInterfaceFactoryBean<T> implements FactoryBean<T> { private Class<T> 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 最終實現app
@Slf4j public class DynamicProxyBeanFactory implements InvocationHandler { private String className; private ApplicationContext applicationContext; private Map<ClientType, Object> clientMap = 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 接口的全部實現類 Map<String,?> classMap = applicationContext.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 classStr,ApplicationContext applicationContext,Class<T> mapperInterface) { ClassLoader classLoader = mapperInterface.getClassLoader(); Class<?>[] interfaces = new Class[]{mapperInterface}; DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory(classStr,applicationContext); return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy); } }
以上即是註解獲取目標類,動態代理提供默認實現,並注入到Spring容器的核心代碼。ide
@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優化代碼待續post
參考文章https://blog.csdn.net/qq_2059...單元測試