在一个项目开发中,通常会把项目分为
一、DAO层(数据访问层):专门负责数据库交互 CRUD(增查改删),好比在mysql数据库里生成一条订单数据。java
二、Service层(业务逻辑层) : 负责业务逻辑的处理,好比购买东西的业务,须要调用DAO层的方法扣减商品记录里的库存数量,而后生成一条订单记录。mysql
三、Controller层(控制层) : 接收页面的请求,调用业务逻辑层去处理,将业务逻辑层处理返回的结果返回给页面。spring
spring中对每一层都提供了相应的注解进行标识:sql
spring还提供了 @Component 组件,没有明确的角色,只是标明该类要注册到spring容器中。数据库
spring可使用 @ComponentScan 注解扫描指定包下标有上面那些注解的类注册到spring容器中。数组
一、基础使用app
下面配置类使用了包扫描注解@ComponentScan,并指定了扫描的包名为com.suzhe.spring.basic.scan, spring启动的时候就会扫描该包下全部的符合条件的类,并注入到spring容器中。ide
@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 { }
运行测试.net
@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把指定包下符合条件的类都注册到了容器中
值得注意的是,这些注解都有一个 value属性,是指定注册到spring中实例的name,默认为 类名首字母小写。
咱们能够设置以下
@Service(value = "gs") public class GreetingService { }
再次运行测试,能够看到注册到spring中bean实例的name变成了gs。
同理,其余注解也同样。
二、扩展-包含过滤
注解@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容器中。
同时咱们还能够自定义过滤器,以下
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 被注册了。
同时@ComponentScan还提供了排除的过滤功能:
useDefaultFilters=true excludeFilters = Filter[] :指定扫描的时候按照什么规则排除哪些组件
includeFilters是包含哪些,excludeFilters是排除哪些,其余的都同样,这里再也不作过多的说明。