该项目为未导入其他框架的Springboot项目,所以只有Springboot的基本功能。项目结构目录如下:
- 创建configuration类
import com.michael.annotation.demo.POJO.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
//1
@Configuration
//2
@ComponentScan(value = {"com.michael.annotation.demo.configuration","com.michael.annotation.demo.service"})
public class MyConfig {
@Bean(name = "person02")
public Person person01(){
return new Person("Michael", 10);
}
@Bean(name = "person03")
public Person person(){
return new Person("Steven", 11);
}
}
- 代码1处注解表示这是一个configuration组件类
- 代码2处为关键注解,指定要被扫描的包下的类,并且把组件类的实例注入到容器中。
- 组件类可以是被@Service, @Repository, @Controller等注解所标识(注解)的类。我们可通过查看源码的方式检查元注解来判断注解的类型和特性。
- @ComponentScan的value为数组类型,可以更加精细地指定要扫描的包。
- 如果@ComponentScan的value只赋值为"com.michael"(扫描该包下的所有子包内被注解的类),启动项目将引发错误。因为@SpringBootApplication注解会自动扫描被注入容器,再次扫描将引发Exception。
Caused by: javax.management.InstanceAlreadyExistsException: org.springframework.boot:type=Admin,name=SpringApplication
- 以MyConfig类当做配置类,并且初始化配置。
import com.michael.annotation.demo.configuration.MyConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
//打印所有在容器中的实例(Bean)
String [] beanNames = applicationContext.getBeanDefinitionNames();
for (String beanName : beanNames
) {
System.out.println(beanName);
}
}
}
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
personService
person02
person03
- 更加精细化地扫描,使用excludeFilters排除要扫描的类。
import com.michael.annotation.demo.POJO.Person;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
@Configuration
//1
@ComponentScan(value = {"com.michael"},
excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = SpringBootApplication.class)
})
public class MyConfig {
@Bean(name = "person02")
public Person person01(){
return new Person("Michael", 10);
}
@Bean(name = "person03")
public Person person(){
return new Person("Steven", 11);
}
}
- 代码1处修改指定扫描的包为项目下所有包,并且添加要排除的类(这里可以其他规则排除)。注意,classes为数组类型。
- 启动项目,发现并没有报错。说明启动类没有被重复注入。
输出:
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
personService
person02
person03
- 更加精细化地扫描,使用includeFilters指定只要扫描的类。这里需要注意,需要把useDefaultFilters设置为false,这样就能把默认扫描规则全部禁止,再定义更为严格的只扫描哪些类的规则。
- @ComponentScan 为可重复注解的注解,所以可以重复注解类去定义多个规则。
- 或者使用@ComponentScans去替代多个@ComponentScan