Spring中对没有实现类的接口进行曾强

说明

对没有实现类的接口进行增强,此场景在Spring中比较常见。最典型的两个就是Mybatis和feign的调用。其主要是通过FactoryBean实现的。

实现

通过实现BeanDefinitionRegistryPostProcessor进行指定路径下包的扫描.

@Component
@Slf4j
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    public MyBeanDefinitionRegistryPostProcessor() {
        System.out.println("MyBeanDefinitionRegistryPostProcessor");
    }


    @Override  //紧接着执行
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }

    @Override  //先执行的
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        //自定义扫描器
        CustomClassPathScanner customClassPathScanner = new CustomClassPathScanner(registry);
        //不加的话类扫描不上
        customClassPathScanner.addIncludeFilter((metadataReader, metadataReaderFactory) -> true);
        //对指定包下的类进行扫描
        customClassPathScanner.doScan("com.spring.demo.interfaceproxy");
    }
}

其中CustomClassPathScanner为自定义包扫描器。

public class CustomClassPathScanner extends ClassPathBeanDefinitionScanner {
    public CustomClassPathScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }


    private final Class<? extends CustomProxyFactoryBean> mapperFactoryBeanClass = CustomProxyFactoryBean.class;
    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //获取包扫描后BeanDefinition
        Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
        for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
            GenericBeanDefinition beanDefinition = (GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition();
            String beanClassName = beanDefinition.getBeanClassName();
            beanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanClassName);
            //定义beanClass为实现的FactoryBean的实现。
            beanDefinition.setBeanClass(mapperFactoryBeanClass);

        }

        return beanDefinitionHolders;
    }

    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return true;
    }
}

CustomProxyFactoryBean为实现了FactoryBean接口的实现。通过在getObject中生成代理类。

public class CustomProxyFactoryBean<T> implements FactoryBean<T> {


    private Class<T> mapperInterface;


    public CustomProxyFactoryBean(Class<T> mapperInterface) {
        this.mapperInterface = mapperInterface;
    }

    @Override
    public T getObject() throws Exception {
        //需要这样传   new Class[] { mapperInterface },因为没有实现类,直接传当前接口
        //否则没法 TestService bean = applicationContext.getBean("testService", TestService.class);
        return (T) Proxy.newProxyInstance(
                mapperInterface.getClassLoader(),
                new Class[]{mapperInterface}, new CustomMapperProxy<T>());

    }

    @Override
    public Class<T> getObjectType() {
        return this.mapperInterface;
    }

}

在getObject方法中,通过jdk动态代理生成对应接口的实现类。CustomMapperProxy为具体的代理实现类。

public class CustomMapperProxy<T> implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        return UUID.randomUUID().toString();
    }
}

测试

定义controller

@Resource
private TestService testService;

@GetMapping("/test/proxy")
public Object testProxy() {
  return testService.test();
}
curl --location 'http://127.0.0.1:8081/test/proxy'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值