目录
1、XML方式注入
-
set方式注入
-
构造方法注入
2、注解方式注入
-
@Component + @ComponentScan
-
@Configuration + @Bean + @ComponentScan
-
@Import
3、实现ImportBeanDefinitionRegistrar接口
4、实现FactoryBean
5、实现BeanDefinitionRegistryPostProcessor
一、XML方式注入
在现在这个Springboot横行的年代,以XML来注入的方式可能已经不多见了,因为压根用不着,但毕竟是注入方式之一也得提一提,这种方式就是依赖于XML的解析来获取我们需要注入的Bean对象
常见的方式有:set方法注入、构造方法注入
这里举几个常见的例子:
1、set方式注入
测试:
2、构造方法注入
测试:
二、注解方式注入
1、@Component + @ComponentScan
我们开发中常用的 @Service 和 @Controller都是@Component下的注解,需要配合@ComponentScan注解才能被扫描到并放入IOC容器中
为什么平时却没用 @ComponentScan注解呢 ?
因为平时用的都是Springboot,Springboot启动类上的 @SpringbootApplication注解类下已经带有 @ComponentScan注解了,默认扫描启动类同级包下的 @Component
例子如下:
我们先准备一个获取IOC容器内bean 的工具类 SpringUtils:
测试要注入的Bean实体类:
可以看到报错了,压根找不到这个bean,因为我们上面说过了springboot默认扫描的是启动类同级下的路径,我们把启动类放到了独立的包下,所以扫描不到了,这时候我们要么在用@ComponentScan注解配置一次扫描路径,要么把启动类提出来,我这里演示前者
我们在启动类上加上@ComponentScan注解配置一次扫描路径,就可以看到注入成功啦
2、@Configuration + @Bean + @ComponentScan
@Configuration注解相信大家也都不陌生,这个注解同样要配合@ComponentScan使用,那到底和@Component有什么区别呢 ?
@Configuration注入的是CGlib代理类,@Component注入的是类本身
我们与@Component一样准备个@Configuration注入类:
可以看到Bean类的本质区别,难道为了这个就搞了@Configuration注解吗?当然不是,这个注解还可以配合@Bean注解一起使用,用来同时注入多个Bean
这样的@Bean可以在同一个类中注入多个,所以@Component更多的用来注入配置文件类,@Configuration 更多的用来注入多个实例类
3、@Import
这种方式一般用在第三方包的加载比较多,使用起来呢也简单需要注入哪个Bean,导入哪个Bean的class就可以了,例如:
这个注解使用得注意,一定要能被扫描到才行,可以直接放在启动类上,如果是普通需要配合@Component或者@Configuration来使用,因为此注解单独使用是不会被扫描到的,也就不会被加载了
在一个注解上导入多个Bean要写这么多可能不是很优雅,所以还可以配合ImportSelector接口使用:
4、实现 ImportBeanDefinitionRegistrar接口
看接口名称就知道了是不是有点像Bean的注册接口,需要配合@Import使用:
测试:
我们平时开发中常用的openfeign也是采用的这种方式:
5、实现FactoryBean
用这个得先搞清楚FactoryBean和BeanFactory的区别:
-
BeanFactory:IOC容器顶层接口,用来Bean容器管理
-
FactoryBean:是一个bean,是一个能产生bean的工厂,本身也会作为bean给容器管理,所以作为一个能产生Bean的工厂,我们可以自定义Bean(这也是最关键的点)
让我们来看看怎么用:
测试:
可以看到通过Class无论是工厂bean还是工厂生产的bean我们都可以获取,但是发现通过beanName获取bean的区别没有,我们通过工厂的beanName获取到的是实际生产的对象,
要获取真正的工厂需要在beanName前面加上&
为什么通过工厂的beanName获取到的是实际生产的对象 ?
其实从上述注入的过程中也能看到我们往容器中注入的其实是工厂Bean,并没有注入工厂生产的那个对象(可以打印容器所有的beanName验证),可以理解为在从容器中获取Bean的时候有判断是否实现了FactoryBean接口,实现了则会调用该bean的getObject()方法返回,所以此时会返回实际工厂生产的对象了