资讯专栏INFORMATION COLUMN

SpringBoot 动态代理|反射|注解(四)- 动态代理对象注入到Spring容器

lingdududu / 2452人阅读

摘要:上一篇动态代理反射注解优化代码三注解本篇我们将实现通过代理生成的对象注入到容器中。单元测试优化代码待续参考文章

上一篇: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> 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> 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 通过动态代理创建默认实现类

@Slf4j
@Data
public class HandlerInterfaceFactoryBean implements 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 最终实现

@Slf4j
public class DynamicProxyBeanFactory implements InvocationHandler {

    private String className;
    private ApplicationContext applicationContext;

    private Map 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 classMap = applicationContext.getBeansOfType(Class.forName(className));
        log.info("DynamicProxyBeanFactory className:{} impl class:{}",className,classMap);

        for (Map.Entry 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 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);
    }
}

以上便是注解获取目标类,动态代理提供默认实现,并注入到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...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/75310.html

相关文章

  • SpringBoot 动态代理|反射|注解|AOP 优化代码(三)-注解

    摘要:上一篇动态代理反射注解优化代码二反射我们实现了通过反射完善找到目标类,然后通过动态代理提供默认实现,本篇我们将使用自定义注解来继续优化。下一篇动态代理反射注解四动态代理对象注入到容器 上一篇SpringBoot 动态代理|反射|注解|AOP 优化代码(二)-反射 我们实现了通过反射完善找到目标类,然后通过动态代理提供默认实现,本篇我们将使用自定义注解来继续优化。 创建注解 1.创建枚举...

    Charles 评论0 收藏0
  • SpringBoot 动态代理|反射|注解|AOP 优化代码(二)-反射

    摘要:动态代理反射注解优化代码一动态代理提供接口默认实现我们抛出问题,并且提出解决问题的第一步的方法。重写动态代理类,实现通过的查找出传入的所有泛型的实现下一篇动态代理反射注解优化代码三注解 SpringBoot 动态代理|反射|注解|AOP 优化代码(一)-动态代理提供接口默认实现 我们抛出问题,并且提出解决问题的第一步的方法。下面我们继续深入,动态代理和反射继续解决我们的问题。 改动代...

    spacewander 评论0 收藏0
  • spring 入门 2 自动装配和aop

    摘要:使用注解配置一步骤为主配置文件引入新的命名空间约束导入约束开启使用注解代理配置文件在中指定扫描包下所有类的注解扫描时会扫描指定包下的所有子孙包在类中使用注解完成配置等二将对象注册到容器将注册到容器中,相当于层层层三修改对象的作用范 使用注解配置spring 一、步骤 1.为主配置文件引入新的命名空间(约束) 导入spring-context-4.2.xsd schema约束 show...

    JasinYip 评论0 收藏0
  • Spring入门IOC和AOP学习笔记

    摘要:入门和学习笔记概述框架的核心有两个容器作为超级大工厂,负责管理创建所有的对象,这些对象被称为。中的一些术语切面切面组织多个,放在切面中定义。 Spring入门IOC和AOP学习笔记 概述 Spring框架的核心有两个: Spring容器作为超级大工厂,负责管理、创建所有的Java对象,这些Java对象被称为Bean。 Spring容器管理容器中Bean之间的依赖关系,使用一种叫做依赖...

    wenyiweb 评论0 收藏0
  • Spring自定义注解不生效原因解析及解决方法

    摘要:自定义注解不生效原因解析及解决方法背景项目中,自己基于实现了一套缓存注解。但是最近出现一种情况缓存竟然没有生效,大量请求被击穿到层,导致压力过大。至此,问题得到解决。 自定义注解不生效原因解析及解决方法 背景: 项目中,自己基于spring AOP实现了一套java缓存注解。但是最近出现一种情况:缓存竟然没有生效,大量请求被击穿到db层,导致db压力过大。现在我们看一下具体代码情形(代...

    xbynet 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<