0
点赞
收藏
分享

微信扫一扫

将 Bean 放入 Spring 容器中的五种方式


文章目录

  • ​​1.@Configuration + @Bean​​
  • ​​2.@Componet + @ComponentScan​​
  • ​​3.@Import注解导入​​
  • ​​3.1 @Import直接导入类​​
  • ​​3.2 @Import + ImportSelector​​
  • ​​3.3 @Import + ImportBeanDefinitionRegistrar​​
  • ​​3.4 @Import + DeferredImportSelector​​
  • ​​4.使用FactoryBean接口​​
  • ​​5.使用 BeanDefinitionRegistryPostProcessor​​

1.@Configuration + @Bean

@Configuration
public class MyConfiguration {
@Bean
public Person person() {
Person person = new Person();
person.setName("spring");
return person;
}
}

2.@Componet + @ComponentScan

@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 + '\'' +
'}';
}
}

@ComponentScan(basePackages = "com.springboot.*")
public class Demo1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

3.@Import注解导入

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

/**
* 用于导入一个class文件
* {@link Configuration @Configuration}, {@link ImportSelector},
* {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
*/
Class<?>[] value();

}

3.1 @Import直接导入类

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类,然后尝试从applicationContext中取,成功拿到
**/
@Import(Person.class)
public class Demo1 {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

3.2 @Import + ImportSelector

@Import(MyImportSelector.class)
public class Demo1 {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.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.springboot.pojo.Person"};
}
}

自定义了一个 MyImportSelector 实现了 ImportSelector 接口,重写selectImports 方法,然后将我们要导入的类的全限定名写在里面即可

3.3 @Import + ImportBeanDefinitionRegistrar

@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// 构建一个beanDefinition, 关于beanDefinition我后续会介绍,可以简单理解为bean的定义.
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
// 将beanDefinition注册到Ioc容器中.
registry.registerBeanDefinition("person", beanDefinition);
}
}

3.4 @Import + DeferredImportSelector

@Import(MyDeferredImportSelector.class)
public class Demo1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.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()};
}
}

DeferredImportSelector 它是 ImportSelector 的子接口, 它和Spring Boot中的自动导入配置文件 延迟导入有关.

4.使用FactoryBean接口

FactoryBean 是一个Bean, BeanFactory 为ioc 工厂

@Configuration
public class Demo1 {
@Bean
public PersonFactoryBean personFactoryBean() {
return new PersonFactoryBean();
}

public static void main(String[] args) {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
Person bean = applicationContext.getBean(Person.class);
System.out.println(bean);
}
}

class PersonFactoryBean implements FactoryBean<Person> {

/**
* 直接new出来Person进行返回.
*/
@Override
public Person getObject() throws Exception {
return new Person();
}
/**
* 指定返回bean的类型.
*/
@Override
public Class<?> getObjectType() {
return Person.class;
}
}

5.使用 BeanDefinitionRegistryPostProcessor

这种方式也是利用到了 ​​BeanDefinitionRegistry​​​, 在Spring容器启动的时候会执行 ​​BeanDefinitionRegistryPostProcessor​​​ 的 ​​postProcessBeanDefinitionRegistry​​ 方法。

等​​beanDefinition​​​加载完毕之后, 对 ​​beanDefinition​​​ 进行后置处理, 可以在此进行调整IOC容器中的​​beanDefinition​​​,从而干扰到后面进行初始化​​bean​​。

public class Demo1 {
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 {

}
}


举报

相关推荐

0 条评论