- 一、五种方式简介
- 二、五种方式具体介绍
- 1、@Configuration + @Bean
- 2、@Componet + @ComponentScan
- 3、@import注解导入
- 1、import直接导入类
- 2、@import + importSelector
- 3、@import + importBeanDefinitionRegistrar
- 4、@import + DeferredimportSelector
- 4、使用FactoryBean接口
- 5、使用 BeanDefinitionRegistryPostProcessor
- @Configuration + @Bean
- @ComponentScan + @Component
- @import 配合接口进行导入
- 使用FactoryBean。
- 实现BeanDefinitionRegistryPostProcessor进行后置处理。
@Configuration用来声明一个配置类,然后使用 @Bean 注解,用于声明一个bean,将其加入到Spring容器中。这种方式是我们最常用的一种
@Configuration
public class MyConfiguration {
@Bean
public Person person() {
Person person = new Person();
person.setName("spring");
return person;
}
}
2、@Componet + @ComponentScan
@Componet中文译为组件,放在类名上面,然后@ComponentScan放置在我们的配置类上,然后可以指定一个路径,进行扫描带有@Componet注解的bean,然后加至容器中。这种方式也较为常用,spring扫描包路径就是使用这种方式,这样可以一下子扫描很多个bean到容器
// 该类在com.shawn.*包下面
@Component
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
'}';
}
}
/
Class>[] value();
}
1、import直接导入类
直接使用@import导入了一个类,然后自动的就被放置在IOC容器中了。注意我们的Person类上 就不需要任何的注解了,直接导入即可
public class Person {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + ''' +
'}';
}
}
@import(Person.class)
public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
2、@import + importSelector
自定义了一个MyimportSelector 实现了 importSelector 接口,重写selectimports方法,然后将我们要导入的类的全限定名写在里面即可导入
@import(MyimportSelector.class)
public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyimportSelector implements importSelector {
@Override
public String[] selectimports(Annotationmetadata importingClassmetadata) {
//这里需要具体到类名
return new String[]{"com.shawn.Person"};
}
}
3、@import + importBeanDefinitionRegistrar
这种方式需要实现 importBeanDefinitionRegistrar 接口中的方法。BeanDefinition可以简单理解为bean的定义(bean的元数据),也是需要放在IOC容器中进行管理的,先有bean的元数据,applicationContext再根据bean的元数据去创建Bean。
@import(MyimportBeanDefinitionRegistrar.class)
public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
// 构建一个beanDefinition
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
// 将beanDefinition注册到Ioc容器中
registry.registerBeanDefinition("person", beanDefinition);
}
}
4、@import + DeferredimportSelector
这种方式也需要我们进行实现接口,其实它和@import的第二种方式差不多,DeferredimportSelector 它是 importSelector 的子接口,所以实现的方法和第二种无异。只是Spring的处理方式不同,它和Spring Boot中的自动导入配置文件延迟导入有关,非常重要
@import(MyDeferredimportSelector.class)
public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyDeferredimportSelector implements DeferredimportSelector {
@Override
public String[] selectimports(Annotationmetadata importingClassmetadata) {
// 也是直接将Person的全限定名放进去
return new String[]{Person.class.getName()};
}
}
上述三类还可以搭配@Configuration注解使用,用于导入一个配置类
4、使用FactoryBean接口FactoryBean接口和BeanFactory不一样,BeanFactory顾名思义 bean工厂,它是IOC容器的顶级接口。
下述代码通过@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,注意,我没有向容器中注入 Person, 而是直接注入的 PersonFactoryBean 然后从容器中拿Person这个类型的bean,成功运行。
@Configuration
public class Demo {
@Bean
public PersonFactoryBean personFactoryBean() {
return new PersonFactoryBean();
}
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class PersonFactoryBean implements FactoryBean {
@Override
public Person getObject() throws Exception {
return new Person();
}
@Override
public Class> getObjectType() {
return Person.class;
}
}
5、使用 BeanDefinitionRegistryPostProcessor
这种方式也是利用到了 BeanDefinitionRegistry,在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,大概意思就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。
下述代码中我们手动向beanDefinitionRegistry中注册了person的BeanDefinition,最终成功将person加入到applicationContext中
public class Demo {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor();
applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
applicationContext.refresh();
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}
class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
registry.registerBeanDefinition("person", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
参考文章
https://blog.csdn.net/weixin_43741092/article/details/120176466
https://mp.weixin.qq.com/s/NpTNVGqU4dQwwgec3X4ibg



