上一篇:SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解
本篇我们将实现通过代理生成的对象注入到spring容器中。
首先需要实现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注解的接口,这些接口就需要通过动态代理提供默认实现
*/
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 通过动态代理创建默认实现类
@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 最终实现
@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容器的核心代码。
单元测试
@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优化代码待续
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。