包扫描的方式
如果没有设置包扫描路径,Spring 不会主动去注册 bean
XML方式配置包扫描
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="com.demon" />
</beans>
注解方式配置包扫描
会扫描包路径下所有的包含 @Component 注解的类:
- @Controller
- @RestController
- @Service
- @Repository
- @Component
package com.demon.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
* 配置类
* @author Demon-HY
* @date 2019-12-9
*/
@ComponentScan("com.demon")
@Configuration
public class Config {
}
简单使用举例
写几个上面提到的注解
UserController.java
package com.demon.controller;
import org.springframework.stereotype.Controller;
/**
* @author Demon-HY
* @date 2019-12-9
*/
@Controller
public class UserController {
}
UserService.java
package com.demon.service;
import org.springframework.stereotype.Service;
/**
* @author Demon-HY
* @date 2019-12-9
*/
@Service
public class UserService {
}
UserDao.java
package com.demon.dao;
import org.springframework.stereotype.Repository;
/**
* @author Demon-HY
* @date 2019-12-9
*/
@Repository
public class UserDao {
}
导入 Spring 测试框架需要的包
<!--测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
测试用例
package com.demon;
import com.demon.config.Config;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @author Demon-HY
* @date 2019-12-9
*/
public class IOCTest {
@Test
public void test() {
// 通过注解方式生成 Spring 上下文
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
// 打印容器中注册的bean
String[] beanDefinitionNames = context.getBeanDefinitionNames();
for (String name : beanDefinitionNames) {
System.out.println(name);
}
}
}
打印结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
config
userController
userDao
userService
user
@ComponentScan 注解中常用参数详解
value/basePackages
指定要扫描的包
excludeFilters 排除规则
excludeFilters 里面嵌套了一个@Filter注解,用来设置多个排除规则
@Filter 注解常用参数
FilterType 过滤类型:
- ANNOTATION: 注解
- ASSIGNABLE_TYPE: 类型
- ASPECTJ: ASPECTJ 表达式
- REGEX: 正则表达式
- CUSTOM: 自定义规则
includeFilters 包含规则,和excludeFilters正好相反
例子: 排除 @Controller 注解的类
package com.demon.config;
import com.demon.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/**
* 配置类
* @author Demon-HY
* @date 2019-12-9
*/
@ComponentScan(value = "com.demon", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
@Configuration
public class Config {
}
例子: 只扫描 @Controller 的类
package com.demon.config;
import com.demon.bean.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/**
* 配置类
* @author Demon-HY
* @date 2019-12-9
*/
@ComponentScan(value = "com.demon", includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
})
@Configuration
public class Config {
}
例子: 过滤 UserService 及其子类和实现类
package com.demon.config;
import com.demon.bean.User;
import com.demon.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/**
* 配置类
* @author Demon-HY
* @date 2019-12-9
*/
@ComponentScan(value = "com.demon", excludeFilters = {
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {UserService.class})
})
@Configuration
public class Config {
}
通过自定义规则过滤 bean id 包含 “User” 的类
自定义过滤规则 MyTypeFilter.java
package com.demon.config;
import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;
import java.io.IOException;
/**
* 自定义 @ComponentScan 过滤规则
* @author Demon-HY
* @date 2019-12-9
*/
public class MyTypeFilter implements TypeFilter {
/**
* @param metadataReader 读取到的当前正在扫描的类的信息
* @param metadataReaderFactory 可以获取到其他任何类信息
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
// 获取当前类注解信息
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类资源信息(类路径)
Resource resource = metadataReader.getResource();
// 获取当前类名
String className = classMetadata.getClassName();
if (className.contains("user")) {
return true;
}
return false;
}
}
修改配置类
package com.demon.config;
import com.demon.bean.User;
import com.demon.service.UserService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
/**
* 配置类
* @author Demon-HY
* @date 2019-12-9
*/
@ComponentScan(value = "com.demon", excludeFilters = {
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
})
@Configuration
public class Config {
}
执行上面写的那个测试用例
UserController,UserService,UserDao 都被过滤掉了,User类没有被过滤掉是因为,User是我们自己在Config.java中设置的,不会被拦截
咖啡小馆
QQ群: 823971061 点击按钮入群