Spring注入Bean的几种方式
# 前言
Spring作为Java程序员必备,核心之一就是Spring的IOC思想,对象的创建都依赖于Spring容器,那么注入一个baen到容器中有哪些方法呢,你知道几种,一起来看看。
# 1.XML方式
最早接触Java还是ssh那一套,所有bean都是依赖xml配置的方式注入的,而xml又可以有四种方式:Set方法注入,构造方法注入, 静态工厂注入和非静态工厂注入。这里以Set方法注入为例:
<bean name="product" class="com.fire.bean.Product">
<property name="name" value="电脑"></property>
</bean>
2
3
/**
* @Author Mr.Fire
* @Desc
* @Date 2022/7/21
*/
@Data
public class Product {
private String id;
private String name;
}
2
3
4
5
6
7
8
9
10
11
12
# 2.@ComponentScan+注解
这里说的注解就是我们常用的@Component以及他的派生@Controller、@Service、@Repository。这就不多说了。
# 3.JavaConfig注入
JavaConfig即java的配置类,@Configuration+@Bean注解的方式注入bean,可替代以往繁琐的xml形式。
/**
* @Author Mr.Fire
* @Desc
* @Date 2022/7/21
*/
@Configuration
public class BeanConfig {
@Bean
public Product product(){
return new Product();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
# 4.@Import注解
1)导入普通类
Sping4.2后,@Import可以注入普通类的bean实例
/**
* @Author Mr.Fire
* @Desc
* @Date 2022/7/21
*/
public class Order {
...
}
2
3
4
5
6
7
8
@Import({Order.class})
@Configuration
public class BeanConfig {
@Bean
public Product product(){
return new Product();
}
}
2
3
4
5
6
7
8
9
这样就可以在其他地方注入Order这个bean使用了,是不是很神奇。如果要注入多个bean也是可以的,@Import注解的value是个数组。
2)导入Configuration类
更高端的玩法,我们还可以注入Configuration类,比如@EnableSwagger2注解中导入了Swagger2DocumentationConfiguration类。
该类是一个Configuration类,它又导入了另外两个类:
SpringfoxWebMvcConfiguration
SwaggerCommonConfiguration
3)导入ImportSelector接口实现类
在SpringBoot启动注解中往下找,@EnableAutoConfiguration注解中就有使用,这也是自动装配重要的一环,关于自动装配可看这篇文章SpringBoot自动装配
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(AutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
...
}
2
3
4
5
6
7
8
9
4)导入ImportBeanDefinitionRegistrar接口实现类
public class CustomImportSelector implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
RootBeanDefinition roleBeanDefinition = new RootBeanDefinition(Role.class);
registry.registerBeanDefinition("role", roleBeanDefinition);
RootBeanDefinition userBeanDefinition = new RootBeanDefinition(User.class);
userBeanDefinition.setScope(ConfigurableBeanFactory.SCOPE_PROTOTYPE);
registry.registerBeanDefinition("user", userBeanDefinition);
}
}
2
3
4
5
6
7
8
9
10
11
12
重写registerBeanDefinitions方法,在该方法中我们可以获取BeanDefinitionRegistry对象,通过它去注册bean。 不过在注册bean之前,我们先要创建BeanDefinition对象,它里面可以自定义bean的名称、作用域等很多参数。 然后在MyConfig类上导入上面的类:
@Import({CustomImportSelector.class})
@Configuration
public class MyConfig {
}
2
3
4
# 5.实现BeanDefinitionRegistryPostProcessor
Spring提供的bean注册接口,注释描述:修改应用程序上下文的内部bean定义注册表标准初始化。所有常规bean定义都将被加载,但是还没有bean被实例化。 这允许进一步添加在下一个后处理阶段开始之前定义bean。在该方法中能够获取BeanDefinitionRegistry对象,它负责bean的注册工作。
另外,BeanFactoryPostProcessor 也可以注册bean。
既然这两个接口都能注册bean,那么他们有什么区别?
- BeanDefinitionRegistryPostProcessor 更侧重于bean的注册
- BeanFactoryPostProcessor 更侧重于对已经注册的bean的属性进行修改,虽然也可以注册bean。
# 6.实现FactoryBean
实现FactoryBean的两个方法
/**
* @Author Mr.Fire
* @Desc
* @Date 2022/7/21
*/
public class TestBeanFactory implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new Product();
}
@Override
public Class<?> getObjectType() {
return Product.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
在之前的Config类中注入testFactoryBeran
/**
* @Author Mr.Fire
* @Desc
* @Date 2022/7/21
*/
@Import({Order.class})
@Configuration
public class BeanConfig {
@Bean
public Product product(){
return new Product();
}
@Bean
public TestBeanFactory testBeanFactory(){
return new TestBeanFactory();
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19