1.@ComponentScan使用
1.新建一个类ConfigComponentScan,类上加@ComponentScan(value ="springanntition.configbean");表明要扫描springanntition.configbean包下的类
@Configuration
@ComponentScan(value ="springanntition.configbean")
public class ConfigComponentScan {
// @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
@Bean
public Person personDy() {
return new Person("ddf", 25);
}
}
就相当于扫描此路径下,然后test包下再建立同路径名下的测试类,pom.xml要添加junit包哦
添加测试类MainTestComponentScan如下
package springannotion.configbean;
import org.junit.Test;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import springanntition.configbean.ConfigComponentScan;
public class MainTestComponentScan {
@Test
public void getIOCBean(){
// 需要写上你需要的配置类哦!
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ConfigComponentScan.class);
// 获取bean的名字
String[] beannames = context.getBeanDefinitionNames();
for (String name : beannames) {
System.out.println(name);
}
}
}
咱们运行一下,除了默认的容器外,标红的就是我们获取到的,configComponentScan是配置类本身的名字,mainConfig是上一篇讲解建立的配置类,以及@Bean的配置全部都获取到了。
我们再建立一个controller类和service类来测试@ComponentScan数组的方式
package anntiontest;
import org.springframework.stereotype.Controller;
@Controller
public class TeseController {
}
package anntiontest;
import org.springframework.stereotype.Service;
@Service
public class TestService {
}
到配置里更改@ComponentScan注解
@Configuration
@ComponentScan(value = {"springanntition.configbean","anntiontest"})
public class ConfigComponentScan {
// @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
@Bean
public Person personDy() {
return new Person("ddf", 25);
}
}
运行测试类,发现新添加的类名扫描出来了
其实这个@ComponentScan就相当于<context:component-scan>标签的使用
<?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学习 -->
<!-- 包扫描、只要标注了@Controller、@Service、@Repository、@Component这4个里的任意一个组件,那么他们都会自动的扫描加入到容器中 -->
<context:component-scan base-package="springanntition.configbean"></context:component-scan>
<!-- bean注入学习 -->
<!-- scope="prototype" -->
<bean id="person" class="springorgin.demo.configbean.Person">
<!-- property是以属性注入 -->
<property name="age" value="18"></property>
<property name="name" value="df"></property>
</bean>
</beans>
2.ComponentScan指定扫描与排除扫描
2.1 excludeFilters
我们也可以按照条件进行进行扫描。ctrl+点击@ComponentScan进源码
includeFilters:Filter[]数组,指定扫描时候只需要包含哪些组件
excludeFilters:是一个Filter数组,指定扫描的时候按照什么规则排除那些组件
我们在配置文件ConfigComponentScan类里加上如下配置,FilterType.ANNOTATION:这个是过滤类型,过滤类型可以有多种方式此处ANNOTATION就是按注解方式指定Controller,讲解完includeFilters在详细说Filter下的type
package springanntition.configbean;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import springorgin.demo.configbean.Person;
@Configuration
// @ComponentScan value:指定要扫描的包,可以是单个或多个的形式
// 过滤不扫描Controller类
@ComponentScan(value = {"springanntition.configbean", "anntiontest"},excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = Controller.class)
})
public class ConfigComponentScan {
// @Bean含义:给容器中注册一个Bean;类型为返回值类型,id默认是用方法名作为id,也可以起别名称
@Bean
public Person personDy() {
return new Person("ddf", 25);
}
}
运行测试类,发现已经没有了Controller
2.2 includeFilters
咱们再来说说指定哪个注解扫描,在配置文件更改以下,添加一个useDefaultFilters的配置=false,原因是默认@ComponentScan默认是扫描全部的,在spring.xml里如果要指定扫描也是需要配置一个默认扫描为false的useDefaultFilters
@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
}, useDefaultFilters = false)
运行测试类
2.3includeFilters的Type讲解
下面我们来说以下Filter的方式有哪些?
includeFilters =Filter[] 指定扫描时候只需要包含哪些组件
FilterType.ANNOTATION:这个是注解方式,我们也实践过了
FilterType.ASSIGNABLE_TYPE:按照给定的类型,不管它的子类还是什么
FilterType.CUSTOM:自定义过滤类型,自定义类型需要实现TypeFilter
我们来实践一下FilterType.ASSIGNABLE_TYPE方式,配置类里加上如下,指定扫描@Controller并且指定扫描TestService类
@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TestService.class),
}, useDefaultFilters = false)
运行测试类,我们看到TestService已经扫描到了
还有一种是自定义类型,我们来实践下,自定义方式和上面两种方式不一样,需要新创建一个类,并且实现 TypeFilter类
新建一个MyTypeFilter类,实现TypeFilter,然后根据参数获取到我们需要的信息,根据信息扫描需要的组件,如果返回true就是匹配扫描,返回false就是不匹配
package springanntition.configbean;
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;
public class MyTypeFilter implements TypeFilter {
/*
metadataReader:读取到的当前正在扫描的类的信息
metadataReaderFactory:可以获取到其他任何类信息的
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 获取当前类注解的信息
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
// 获取当前正在扫描的类的信息
ClassMetadata classMetadata = metadataReader.getClassMetadata();
// 获取当前类的资源信息(类的路径)
Resource resource = metadataReader.getResource();
// 可以获取类名称
String calssName = classMetadata.getClassName();
System.out.println("--->" + calssName);
// 根据类名称扫描带er字样的属性
if (calssName.contains("er")) {
return true;
}
// 返回return false就是一个都不匹配
return false;
}
}
扫描配置类配置如下
@ComponentScan(value = {"springanntition.configbean", "anntiontest"}, includeFilters = {
/* @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Controller.class),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = TestService.class),*/
@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}, useDefaultFilters = false)
运行出来了,包含er的都被扫描到了
咱们在ctrl+@ComponentScan点击进来以后发现有个@Repeatable,这个组件的意思是重复组件,就是说类上可以写多个@ComponentScan,限于jdk1.8哦
@ComponentScan(value = {"springannotion", "anntiontest"})
@ComponentScan()
如果不是JDK1.8不支持重复组件,也可以使用如下@ComponentScans来使用
@ComponentScans(value = {
@ComponentScan(value = {"springannotion", "anntiontest"})
})