3、Spring-包扫描注解@ComponentScan

在一个项目开发中,一般会把项目分为
1、DAO层(数据访问层):专门负责数据库交互 CRUD(增查改删),比如在mysql数据库里生成一条订单数据。

2、Service层(业务逻辑层) : 负责业务逻辑的处理,比如购买东西的业务,需要调用DAO层的方法扣减商品记录里的库存数量,然后生成一条订单记录。

3、Controller层(控制层) : 接收页面的请求,调用业务逻辑层去处理,将业务逻辑层处理返回的结果返回给页面。

spring中对每一层都提供了相应的注解进行标识:

spring还提供了 @Component 组件,没有明确的角色,只是标明该类要注册到spring容器中。

spring可以使用 @ComponentScan 注解扫描指定包下标有上面那些注解的类注册到spring容器中。

1、基础使用

下面配置类使用了包扫描注解@ComponentScan,并指定了扫描的包名为com.suzhe.spring.basic.scan, spring启动的时候就会扫描该包下所有的符合条件的类,并注入到spring容器中。

@Configuration  //告诉Spring这是一个配置类
//包扫描:如果没有配置则默认扫描为当前类所在包及其子包
@ComponentScan(value = "com.suzhe.spring.basic.scan")
public class ScanConfig {
}

添加几个类:其中Message1 没有注解,不符合条件

@Controller
public class GreetingController {
}
@Service
public class GreetingService {

}
@Repository
public class GreetingDao {
    public String getMessage(){
        return "welcome";
    }
}
@Component
public class Message {

}
public class Message1 {

}

运行测试

	@Test
	public void test1(){
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanConfig.class);
		//获取容器中所有注册的bean的name,返回一个数组
		String[] names = app.getBeanDefinitionNames();
		for(String name:names){
			System.out.println(name);
		}
	}

可以看出spring把指定包下符合条件的类都注册到了容器中

654b40816ad25d28a6badc285aaa2dbc60b.jpg

值得注意的是,这些注解都有一个 value属性,是指定注册到spring中实例的name,默认为 类名首字母小写。

20b3274a59b49623879227ac27e2c7dfab7.jpg

我们可以设置如下

@Service(value = "gs")
public class GreetingService {

}

再次运行测试,可以看到注册到spring中bean实例的name变成了gs。

cf58fd24416f6a49f25891ecb4bd7337bba.jpg

同理,其他注解也一样。

 

2、扩展-包含过滤

注解@ComponentScan 还提供includeFilters属性指定扫描的时候只需要包含哪些组件。

其中Filter有下面几种过滤类型:

FilterType.ANNOTATION:按照注解
FilterType.ASSIGNABLE_TYPE:按照给定的类型;
FilterType.ASPECTJ:使用ASPECTJ表达式
FilterType.REGEX:使用正则指定
FilterType.CUSTOM:使用自定义规则

示例配置类1

该类配置了FilterType.ANNOTATION和FilterType.ASSIGNABLE_TYPE ,那么就只有注解为@Service的类和Message会被注册到spring容器中。

需要注意的是useDefaultFilters设置为false。

@Configuration  //告诉Spring这是一个配置类
//包扫描:如果没有配置则默认扫描为当前类所在包及其子包
@ComponentScan(value = "com.suzhe.spring.basic.scan",includeFilters ={
        @ComponentScan.Filter(type= FilterType.ANNOTATION, classes={Service.class}),
        @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE,classes={Message.class}),
}, useDefaultFilters=false)
public class ScanIncludeConfig {


}

测试运行

	@Test
	public void test2(){
		AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanIncludeConfig.class);
		String[] names = app.getBeanDefinitionNames();
		for(String name:names){
			System.out.println(name);
		}
	}

从下面的结果可以看出,只有两个符合过滤条件的类注入到了spring容器中。

2902a87be5de3251c61ed86a703ed58fbee.jpg

 

同时我们还可以自定义过滤器,如下

public class CustomTypeFilter implements TypeFilter{
	private ClassMetadata classMetadata;
	/*
	 * MetadataReader:读取到当前正在扫描类的信息
	 * MetadataReaderFactory:可以获取到其他任何类信息
	 */
	@Override
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		//获取当前类注解的信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		//获取当前正在扫描的类信息
		classMetadata = metadataReader.getClassMetadata();
		//获取当前类资源(类的路径)
		Resource resource = metadataReader.getResource();
		String className = classMetadata.getClassName();
		System.out.println("----->"+className);
		if(className.contains("Controller")){//当类名包含Controller字符, 则匹配成功,返回true
			return true;
		}
		return false;
	}

}

通过FilterType.CUSTOM 指定过滤器CustomTypeFilter ,那么spring就只会注册符合CustomTypeFilter过滤条件的类。

@Configuration  //告诉Spring这是一个配置类
//包扫描:如果没有配置则默认扫描为当前类所在包及其子包
@ComponentScan(value = "com.suzhe.spring.basic.scan",includeFilters ={
        @ComponentScan.Filter(type=FilterType.CUSTOM,classes={CustomTypeFilter.class}),
}, useDefaultFilters=false)
public class ScanIncludeCustomConfig {


}

测试运行

@Test
public void test02(){
   AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(ScanIncludeCustomConfig.class);
   String[] names = app.getBeanDefinitionNames();
   for(String name:names){
      System.out.println(name);
   }
}

可以看到只有符合条件的GreetingController 被注册了。

ad297013ee54896f08f9507e3f197924be5.jpg

 

同时@ComponentScan还提供了排除的过滤功能:

useDefaultFilters=true excludeFilters = Filter[] :指定扫描的时候按照什么规则排除哪些组件

includeFilters是包含哪些,excludeFilters是排除哪些,其他的都一样,这里不再做过多的说明。

转载于:https://my.oschina.net/suzheworld/blog/3008060

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值