动态代理注册到Spring容器

1.前言

在项目中,遇到了一个这样的需求。
我们有一个默认的持久化层实现:

public class BasePersistence {
    String db;
    String item;

    public Id queryId() {
    }
    ...
}

不同的表的持久层如果来完成的话,就需要继承自这个默认化持久层。
比如我们有一个Vendor的表,则对应的持久层应该是:

@Resource
public class VendorPersistenceImpl extends BasePersistence implements IPersistence {
    ...
}

有一个问题是能不能通过简单的继承一个接口即能完成逻辑的实现,而不用显式子的还要完成一个实现类。
比如

@Persistence
public interface VendorPersistence extends IPersistence {
}

对于这种情景,一个比较直观的方式就是通过反射+动态代理来进行。

2. 反射+代理:

以下扫描所有注解了Persistence的类:

    private Set> getPersistenceClasses() {
        Reflections reflections = new Reflections(
                "com.lucifer.proxy.*",
                new TypeAnnotationsScanner(),
                new SubTypesScanner()
        );
        return reflections.getTypesAnnotatedWith(Persistence.class);
    }

针对该类我们可以通过动态代理来进行:

@Slf4j
public class DynamicProxyBeanFactory implements InvocationHandler {
    private BasePersistence persistence;

    public DynamicProxyBeanFactory(BasePersistence persistence) {
        this.persistence = persistence;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
      return method.invoke(proxy, args);
    }

    public static  T newMapperProxy(String db, String item,Class mapperInterface) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        Class[] interfaces = new Class[]{mapperInterface};
        DynamicProxyBeanFactory proxy = new DynamicProxyBeanFactory(new BasePersistence(db, item));
        return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }
}

调用的时候直接:

public static void main() {
    IPersistence persistence = DynamicProxyBeanFactory.newMapperProxy("person", "name", IPersistence);
    persistence.findById();
}

如果我们使用Spring的时候,实际可以更加便捷的在Spring加载的时候把生成的代理动态的注册到Spring容器中。

3.动态代理注册到Spring容器

@Slf4j
@Component
public class HandlerBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor, ApplicationContextAware {
    private ApplicationContext applicationContext;

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        /**
         * 获取Peresistence注解的接口,这些接口就需要通过动态代理提供默认实现
         */
        Set> classes = getPersistenceClasses();
        for (Class clazz : classes) {

            Type[] types = clazz.getGenericInterfaces();
            ParameterizedType type = (ParameterizedType) types[0];
            String typeName = type.getActualTypeArguments()[0].getTypeName();

            BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(clazz);
            GenericBeanDefinition definition = (GenericBeanDefinition) builder.getRawBeanDefinition();
            definition.getPropertyValues().add("db", clazz.name());
            definition.getPropertyValues().add("item", "");
            definition.getPropertyValues().add("interfaceClass", clazz);
            definition.getPropertyValues().add("context", applicationContext);
            definition.setBeanClass(DataIoPersistenceInterfaceFactoryBean.class);
            definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
            beanDefinitionRegistry.registerBeanDefinition(clazz.name(), definition);
        }
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
        log.info("------------------------>postProcessBeanFactory");
    }

    /**
     * 通过反射扫描出所有使用HandlerRouterAutoImpl的类
     * @return
     */
    private Set> getAutoImplClasses() {
        Reflections reflections = new Reflections(
                "com.lucifer.proxy.*",
                new TypeAnnotationsScanner(),
                new SubTypesScanner()
        );
        return reflections.getTypesAnnotatedWith(Persistence.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);
    }
}

@Slf4j
@Data
public class DataIoPersistenceInterfaceFactoryBean implements FactoryBean {
    private Class interfaceClass;
    private String typeName;
    private ApplicationContext context;

    @Override
    public T getObject() throws Exception {
        Object object = DataIoDynamicProxyBeanFactory.newMapperProxy(typeName, interfaceClass, context);
        return (T) object;
    }

    @Override
    public Class getObjectType() {
        return interfaceClass;
    }

    @Override
    public boolean isSingleton() {
        return true;
    }
}
@Slf4j
public class DataIoDynamicProxyBeanFactory {

    public static  T newMapperProxy(String typeName, Class mapperInterface,
            ApplicationContext applicationContext) {
        ClassLoader classLoader = mapperInterface.getClassLoader();
        Object target = new SimpleDataIoPersistence<>(Class.forName(typeName),
                applicationContext.getBean(DataIoOperations.class));
        // Create proxy
        ProxyFactory result = new ProxyFactory();
        result.setTarget(target);
        result.setInterfaces(mapperInterface, Persistence.class);
        result.addAdvice(new ProxyPersistence(typeName, mapperInterface));
        return (T) result.getProxy(classLoader);
    }
}

4.参考文章

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

你可能感兴趣的:(动态代理注册到Spring容器)