目录
给容器中注册组件的三种方式
1. 组件注解标注 + 包扫描(适用于自己写的类)
//控制层组件
@Controller
public class PersonController {
}
//业务逻辑层组件
@Service
public class PersonServic {
}
//持久层组件
@Repository
public class PersonDao {
}
//其他组件
@Component
public class Person {
}
包扫描(注解或者xml的方式)
1.使用注解的方式
@ComponentScan(value = "com.xxx")
2.使用xml的方式
<context:component-scan base-package="com.xxx"/>
2. @Bean(适用于第三方包里面的组件)
@Bean("组件id") 默认使用方法名作为id,返回值作为组件的类型
3. @Import(快速给容器中导入一个组件)
@Import的第一种用法
- 直接在配置类上加上注解@Import(要加入到ioc容器中的类的类模板)
@Configuration
@ComponentScan(value = "com.atguigu",excludeFilters = {
//不扫描@controller和service注解,type默认为注解类型,可以不写
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {Myfilter.class})})
@SuppressWarnings("all")
@Import(HashMap.class) //将HashMap类加入到ioc容器中
public class MainConfig {
}
可以看到@Import注解的value时个数组,所以也可以导入多个值
注意:@Import注入的bean默认id为类的全限定名
public @interface Import {
/**
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();
}
@Import(HashMap.class,TreeMap.class) //将HashMap类加入到ioc容器中
public class MainConfig {
}
- 编写测试类
@Test
public void testImport(){
try(ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class)) {
//查看容器中的所有对象
String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 查看打印结果
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
personController
personServic
java.util.HashMap //可以看到ioc容器中已经有hashmap
java.util.TreeMap //可以看到ioc容器中已经有treemap
person
p1
@Import的第二种用法:ImportSelector方式【重点】
这种方式的前提就是一个类要实现ImportSelector接口,假如我要用这种方法,目标对象是Myclass这个类,分析具体如下:
- 创建Myclass类并实现ImportSelector接口
//自定义逻辑返回需要导入的组件
public class MyClass implements ImportSelector {
/**
* @param importingClassMetadata 表示当前被@Import注解给标注的所有注解信息【不是重点】
* @return 就是我们实际上要导入到容器中的组件全类名【重点 】
*/
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
return new String[]{
"java.util.LinkedHashSet",
"java.util.ArrayList"
};
}
}
- 在@Import注解上加入属性自定义类
@Import({HashMap.class, TreeMap.class, MyClass.class})
- 测试类
@Test
public void testImport(){
try(ConfigurableApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfig.class)) {
System.out.println(ioc);
//查看容器中的所有对象
String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
for (String beanDefinitionName : beanDefinitionNames) {
System.out.println(beanDefinitionName);
}
}
}
- 查看打印结果
@Import的第三种用法:ImportBeanDefinitionRegistrar方式
同样是一个接口,类似于第二种ImportSelector用法,相似度80%,只不过这种用法比较自定义化注册,具体如下:
第一步:创建Myclass2类并实现ImportBeanDefinitionRegistrar接口
public class Myclass2 implements ImportBeanDefinitionRegistrar {
//该实现方法默认为空
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
}
}
参数分析:
- 第一个参数:annotationMetadata 和之前的ImportSelector参数一样都是表示当前被@Import注解给标注的所有注解信息
- 第二个参数表示用于注册定义一个bean
第二步:编写代码,自定义注册bean
public class Myclass2 implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//指定bean定义信息(包括bean的类型、作用域...)
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(TestDemo4.class);
//注册一个bean指定bean名字(id)
beanDefinitionRegistry.registerBeanDefinition("TestDemo4444",rootBeanDefinition);
}
}
第三步:编写TestDemo 类,并标注上使用ImportBeanDefinitionRegistrar方式的Myclass2类
@Import({TestDemo2.class,Myclass.class,Myclass2.class})
public class TestDemo {
@Bean
public AccountDao2 accountDao222(){
return new AccountDao2();
}
}
第四步:运行结果
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
personController
personServic
java.util.HashMap
java.util.TreeMap
java.util.LinkedHashSet
java.util.ArrayList
person
p1
TestDemo4444 //可以看到已经在ioc中
4. @Import注解的三种使用方式总结
第一种用法:@Import({ 要导入的容器中的组件 } ):容器会自动注册这个组件,id默认是全类名
第二种用法:ImportSelector:返回需要导入的组件的全类名数组,springboot底层用的特别多【重点 】
第三种用法:ImportBeanDefinitionRegistrar:手动注册bean到容器
以上三种用法方式皆可混合在一个@Import中使用,特别注意第一种和第二种都是以全类名的方式注册,而第三中可自定义方式。
@Import注解本身在springboot中用的很多,特别是其中的第二种用法ImportSelector方式在springboot中使用的特别多,尤其要掌握!