上一篇:SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解

本篇我们将实现通过代理生成的对象注入到spring容器中。
首先需要实现BeanDefinitionRegistryPostProcessor, ApplicationContextAware两个接口,作用分别为:
ApplicationContextAware:可以获得ApplicationContext对象,然后获取Spring容器中的对象
BeanDefinitionRegistryPostProcessor:可以将我们自定义的bean注入到spring容器

@Slf4j@Componentpublic 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@Datapublic 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 最终实现

@Slf4jpublic 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优化代码待续

参考文章https://blog.csdn.net/qq_2059...