前言:组件添加有很多种方式的注解,不同的注解代表不同的含义
- @ComponentScan
- @Bean
- @Configuration
- @Component
- @Service
- @Repository
- @Conditional
- @Primary
- @Lazy
- @Scope
- @Import
- @ImportSelector
- 工厂模式
1.@Configuration:配置类
-
在Spring中,标志着这个注解,会认为这个类为配置类,可以定义自己想要的容器
Full模式(proxyBeanMethods = true):保证每个@Bean组件返回都是单实例的,外部无论对配置类中的这个组件注册方法调用多少次获取的都是之前注册容器中的单实例对象
Lite模式(proxyBeanMethods = false):每个@Bean组件被调用多少次就创建多少个
- 配置类也会被容器管理,配置类中添加到容器中使用@Bean注解。
- 配置类也会被容器管理,配置类中添加到容器中使用@Bean注解。
-
Full模式:在默认下是被激活的,永远都是单实例(proxyBeanMethods = true)
-
Lite模式,是多实例的表现(proxyBeanMethods = false)
2.@ComponentScan 扫描包,对于指定包下的标注的注解,全部都会被扫描
-
指定扫描包下的所有注解
-
指定排除规则:Filter[] excludeFilters
演示排除:service.class
-
定义的格式是Filter【】数组
-
Filter【】定义了type
-
FilterType中可以指定多值(我们目前使用的是注解)
-
按照规则定义排除Service.class注解
-
@ComponentScan(value = "fatcats.top.demo",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Service.class})
})
- 运行结果展示
3.@Component、@Service、@Repository、@Controller 四大注解结合@ComponentScan扫描使用。
- 运行测试类
@Slf4j
public class AnnotationTest {
@Test
public void test1(){
//获取AnnotationConfigApplicationContext上下文
AnnotationConfigApplicationContext annotationConfigApplicationContext =
new AnnotationConfigApplicationContext(MainConfigura.class);
TestAnnotaionBean bean = annotationConfigApplicationContext.getBean(TestAnnotaionBean.class);
log.info("实例bean为:{}",bean);
String[] beanDefinitionNames = annotationConfigApplicationContext.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
log.info("bean 实例为:{}",beanDefinitionName);
}
}
}
- 运行结果如下
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:org.springframework.context.annotation.internalConfigurationAnnotationProcessor
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:org.springframework.context.annotation.internalAutowiredAnnotationProcessor
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:org.springframework.context.annotation.internalCommonAnnotationProcessor
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:org.springframework.context.event.internalEventListenerProcessor
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:org.springframework.context.event.internalEventListenerFactory
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:mainConfigura
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:demoApplication
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:demoComponent
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:demoController
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:demoRepository
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:demoService
- 补充:配置类也被注册到容器中。
因为@Configuration注解也是被@Componenet标注着的
4.@Bean:注册容器
- 在配置类中,使用@Bean注解标注容器,默认id是方法名。
@Bean
public TestAnnotaionBean testBean(){
return new TestAnnotaionBean("创建的msg测试Bean");
}
log打印:
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:testBean
- 可以通过注解更改ID
@Bean("beanTest")
public TestAnnotaionBean testBean(){
return new TestAnnotaionBean("beanTest是通过注解更改的ID");
}
log打印如下
[main] INFO fatcats.top.demo.test.AnnotationTest - 实例bean为:TestAnnotaionBean(msg=beanTest是通过注解更改的ID)
[main] INFO fatcats.top.demo.test.AnnotationTest - bean 实例为:beanTest
5.@Scope:设置作用域
- 关于@Scope中属性:
- prototype : 多实例
- singleton: 单实例
- request : 同一次请求创建一个实例
- session : 同一个session创建一个实例
- 测试prototype 属性值。
- 测试是否还是单实例对象?
6.@Lazy:懒加载
其实就是在容器启动时不创建对象,第一次使用(获取)Bean的时候才创建对象,并且是单实例的
测试结果:
7.@Import:注解导入组件
- 只需要标注注解在配置类上即可。
@Import(TestImportBean.class)
public class MainConfigura {
}
- 使用@Import导入的组件,ID是全类名。
- @ImportSelect注解结合使用。
- 实现ImportSelector接口,重写String[] selectImports(AnnotationMetadata annotationMetadata)方法。
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
//添加全类名组件,返回
return new String[]{"fatcats.top.demo.bean.Red","fatcats.top.demo.bean.Color"};
}
}
- 将实现类添加到@Import中。
结果如下:
8.@Conditional:条件判断
条件装配:满足Conditional指定的条件,则进行组件注入
在SpringBoot底层中,很多自动注入的原理都是依靠这个@ConditionalOnMissingBean注解,进行是否需要自动装配的原则,在类上或者方法上标注这个注解,决定是否需要需要对此类进行生效
测试:
@Configuration
@ConditionalOnMissingBean(name = "tom") //容器中没有tom组件的时候此类生效
public class MyConfig {
@Bean
public User user01(){
System.out.println("创建成功");
return new User("hahah");
}
8.1 User实体类
public class User {
private String name;
}
8.2 Controller测试
@RestController
public class UserController {
@Autowired
User users;
@GetMapping("/hello")
private String sayHello(){
return users.toString();
}
8.3 结果打印: