说明
对没有实现类的接口进行增强,此场景在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;@Overridepublic Set<BeanDefinitionHolder> doScan(String... basePackages) {//获取包扫描后BeanDefinitionSet<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;}@Overrideprotected 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;}@Overridepublic 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>());}@Overridepublic Class<T> getObjectType() {return this.mapperInterface;}}
在getObject方法中,通过jdk动态代理生成对应接口的实现类。CustomMapperProxy
为具体的代理实现类。
public class CustomMapperProxy<T> implements InvocationHandler {@Overridepublic 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'