文章目录
前言
在做项目或写单元测试时,需要对某个特定的bean进行排除,为了方便大家的使用,这里对几种常见的方案进行总结。
常见方法
- 排除指定注解的类-annotation
- 排查指定切面的类-aspectj
- 排除继承至某接口或类的类-assignable
- 排除符合指定匹配规则的类-regex
- 叠加进行排除
- 排除符合自定义规则的类-custom
- 通过BeanDefinitionRegistryPostProcessor进行排除
注源码解释:
"annotation" indicates an annotation to be present or meta-present at the type level in target components;
"assignable" indicates a class (or interface) that the target components are assignable to (extend/implement);
"aspectj" indicates an AspectJ type pattern expression to be matched by the target components;
"regex" indicates a regex pattern to be matched by the target components' class names;
"custom" indicates a custom implementation of the org.springframework.core.type.TypeFilter interface.
代码示例
1、排除指定注解的类-annotation
通过xml配置,可以将配置了@Service注解的类都排除掉
<context:component-scan base-package="com.coderp">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
2、排查指定切面的类-aspectj
采用aspectj过滤,“com.coderp.service.impl…*”:表示下面的包及其子包(包切入点)
<context:component-scan base-package="com.coderp" >
<context:exclude-filter type="aspectj" expression="com.coderp.service.impl..*"/>
</context:component-scan>
采用aspectj过滤,"*…Log":com.coderp所有的包及其子包下,只要有Log类,就会被排除
<context:component-scan base-package="com.coderp" >
<context:exclude-filter type="aspectj" expression="*..Log"/>
</context:component-scan>
3、排除继承至某接口或类的类-assignable
通过xml配置,将Log类或继承Log的类都排除掉
<context:component-scan base-package="com.coderp">
<context:exclude-filter type="assignable" expression="com.coderp.service.impl.Log"/>
</context:component-scan>
4、排除符合指定匹配规则的类-regex
通过xml配置,将符合正则表达式模式的类进行排除
<context:component-scan base-package="com.coderp">
<context:exclude-filter type="regex" expression="com.coderp.service.impl.PayServiceImpl"/>
</context:component-scan>
5、叠加进行排除
通过xml配置,可以对多种过滤方式进行组合,如下组合assignable和aspectj方式
<context:component-scan base-package="com.coderp">
<context:exclude-filter type="assignable" expression="com.coderp.service.impl.Log"/>
<context:exclude-filter type="aspectj" expression="com.coderp.aspect..*"/>
</context:component-scan>
6、排除符合自定义规则的类-custom
自定义过滤规则MyTypeFilter,当返回true则将符合规则的类进行排除,如下的过滤规则会将类名称中包含“PayServiceImpl”的都会被排除。
public class MyTypeFilter implements TypeFilter {
/**
* 当我们实现TypeFilter接口时,需要实现TypeFilter接口中的match()方法,
* match()方法的返回值为boolean类型。当返回true时,表示符合规则,
* 会排除在Spring容器中;当返回false时,表示不符合规则,会包含在Spring容器中。
* @param metadataReader :读取当前正在扫描的类的信息
* @param metadataReaderFactory :可以获取到其它任务类的信息
* @return
* @throws IOException
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
//获取当前类注解的信息
AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
//获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类的资源信息。例如类的路径等信息
try {
Resource resource = metadataReader.getResource();
} catch (Exception e) {
e.printStackTrace();
}
String className = classMetadata.getClassName();
System.out.println("当前正在扫描的类----->"+className);
System.out.println(className.contains("PayServiceImpl"));
return className.contains("PayServiceImpl");
}
}
<context:component-scan base-package="com.coderp" >
<context:exclude-filter type="custom" expression="com.coderp.filter.MyTypeFilter"/>
</context:component-scan>
7、通过BeanDefinitionRegistryPostProcessor进行排除
以上方式都是通过xml配置进行过滤的,当然也可以通过注解进行过滤,那能不能用直接用代码进行过滤呢?显然是可以的,这里利用BeanDefinitionRegistryPostProcessor类进行处理。如下示例,将“payServiceImpl”排除
@Service
public class RemoveRegistyBeanFactoryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
if (beanDefinitionRegistry.containsBeanDefinition("payServiceImpl")){
beanDefinitionRegistry.removeBeanDefinition("payServiceImpl");
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
}
}
总结
通过上面的方法介绍和代码示例,希望能够帮助到大家,关键还是大家多练习,在工作中及时总结。