SpringBoot 動態代理|反射|註解(四)- 動態代理對象注入到Spring容器

上一篇: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...單元測試

相關文章
相關標籤/搜索