说明
对没有实现类的接口进行增强,此场景在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'