将 Bean 注入 Spring 容器的方法

news/2024/11/25 9:32:08/

这里写目录标题

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


1. @Configuration + @Bean

@Configuration 来声明1个配置类,
@Bean 注解声明1个bean,将其加入到Spring容器中。

@Configuration
public class MyConfiguration {@Beanpublic Person person() {Person person = new Person();return person;}
}

2. @Componet + @ComponentScan

@Componet放在类名上面;
@ComponentScan放在配置类上,可以指定一个路径,进行扫描带有@Componet注解的bean,然后加至容器中。

@Component
public class Person {
}@ComponentScan(basePackages = "com.haoqian.beans.*")
public class Demo {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

3. @Import 注解导入

@Import 注解在进行Spring扩展时经常会用到,它经常搭配自定义注解进行使用,然后往容器中导入一个配置文件。

关于@Import注解,它有四种使用方式。@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 {
}/*** 直接使用@Import导入person类**/
@Import(Person.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

3.2 @Import + ImportSelector接口

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

class MyImportSelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.haoqian.beans.Person"};}
}@Import(MyImportSelector.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

3.3 @Import + DeferredImportSelector接口

DeferredImportSelector 它是 ImportSelector 的子接口,所以实现的方法和3.2无异。只是Spring的处理方式不同,它和Spring Boot中的自动导入配置文件 延迟导入有关,非常重要。

class MyDeferredImportSelector implements DeferredImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {// 也是直接将Person的全限定名放进去return new String[]{Person.class.getName()};}
}@Import(MyDeferredImportSelector.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

3.4 @Import + ImportBeanDefinitionRegistrar接口

自定义了一个ImportBeanDefinitionRegistrar接口的实现类,重写registerBeanDefinitions方法,然后将要导入bean的beanDefinition 注入到容器中,容器会创建对应的bean。

class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 构建一个beanDefinition.AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();// 将beanDefinition注册到Ioc容器中.registry.registerBeanDefinition("person", beanDefinition);}
}@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

@Import 还可以搭配@Configuration注解使用,用于导入一个配置类。


4. FactoryBean接口

FactoryBean接口和BeanFactory千万不要弄混了:

  • FactoryBean, 后缀为bean,那么它其实就是一个bean;
  • BeanFactory,顾名思义 bean工厂,它是IOC容器的顶级接口;

使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,注意,没有向容器中注入 Person, 而是直接注入的 PersonFactoryBean 然后可以从容器中拿到Person这个类型的bean。

class PersonFactoryBean implements FactoryBean<Person> {/***  直接new出来Person进行返回.*/@Overridepublic Person getObject() throws Exception {return new Person();}/***  指定返回bean的类型.*/@Overridepublic Class<?> getObjectType() {return Person.class;}
}@Configuration
public class Demo1 {@Beanpublic PersonFactoryBean personFactoryBean() {return new PersonFactoryBean();}public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);Person bean = applicationContext.getBean(Person.class);}
}

5. BeanDefinitionRegistryPostProcessor接口

其实这种方式也是利用到了 BeanDefinitionRegistry,在Spring容器启动的时候会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,大概意思就是等beanDefinition加载完毕之后,对beanDefinition进行后置处理,可以在此进行调整IOC容器中的beanDefinition,从而干扰到后面进行初始化bean。

class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();registry.registerBeanDefinition("person", beanDefinition);}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}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);}
}

http://www.ppmy.cn/news/4331.html

相关文章

三层-生成树-ospf-速端口思科练习实验

♥️作者&#xff1a;小刘在这里 ♥️每天分享云计算网络运维课堂笔记&#xff0c;疫情之下&#xff0c;你我素未谋面&#xff0c;但你一定要平平安安&#xff0c;一 起努力&#xff0c;共赴美好人生&#xff01; ♥️夕阳下&#xff0c;是最美的&#xff0c;绽放&#xff0c;…

大数据呀大数据

大数据 啥是大数据? 我自己的一些经历–>>在做代码开发之前,一直觉得大数据这件事是高大上的一门学问,门槛很高,而且我上大学的时候这个词才刚刚在众多互联网记住中展露头角; 我的个人经历–>> 我上大学时那时候安卓的版本才到安卓4.4,在智能手机出来普及以前,各…

json对象数组集合-第10讲

假设我们有如下是一组数据&#xff1a; { "my_array": [{ "name": "www", "age": 120 }, { "name": "wkf&q…

van-uplaoder保存文件到后端,回显后端接口返回的数据

实现功能&#xff1a;在移动端使用van-uploader组件上传图片&#xff0c;然后调用接口保存到后端数据库&#xff0c;提交保存信息成功后&#xff0c;调用另外的接口返回数据用来回显uploaded的文件&#xff0c;&#xff08;一般正常的返回数据的接口是个图片地址&#xff0c;可…

15 CPP函数重载

函数重载的细节&#xff1a; 1 使用重载函数时&#xff0c;如果数据类型不匹配&#xff0c;C尝试使用类型转换与形参进行匹配&#xff0c;如果转换后有多个函数能匹配上&#xff0c;编译将报错。 2 引用可以作为函数重载的条件&#xff0c;但是调用重载函数的 时候&#xff0…

springboot常用语法库

今天与大家分享springboot常用语法库的基本语法。如果有问题&#xff0c;望大家指教。 目录 1. freemarker是什么 1.1 优点 2. springboot整合freemarker 2.1 pom.xml 2.2 项目配置文件 2.3 Controller 2.4 index.ftl 2.5 常用功能演示 1. freemarker是什么 FreeMarke…

【C++】list的介绍和使用

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;list 的介…

计算机网络实验——路由器的配置静态与RIP配置

前言 由于几个资料和老师给的ppt说的都不清楚&#xff0c;自己也没想到什么很巧妙的归纳方法&#xff0c;写个总结记录一下。 想必静态路由配置的过程中唯一的难点就是ip route这个指令&#xff0c;其他的什么添加接口&#xff0c;设置ip啥的都是基础路由配置中的内容&#xf…