目录
1.xml方式
2.注解方式
2.1@Configuration + @Bean
2.2@Import
3.FactoryBean
4.BeanFactoryPostProcessor
1.xml方式
所有bean的注入都依靠xml文件来完成
方式有:set方法注入,构造注入,字段注入等
set方法注入实例:
<bean name="teacher" class="org.springframework.demo.model.Teacher">
<property name="name" value="张老师"></property>
</bean>
对应实体类方法
public class Teacher {
private String name;
public void setName(String name) {
this.name = name;
}
}
缺点:
1.既要维护代码还要维护配置文件,开发效率低,尤其是配置文件很多的情况
2.编译期间不好排错
3.在解析xml时候,无论是将xml一次性装进内存还是一行行解析都会占用内存资源
2.注解方式
2.1@Configuration + @Bean
当我们需要引入第三方的 jar
包时,可以用 @Bean
注解来标注,同时需要搭配 @Configuration
来使用
-
@Configuration
用来声明一个配置类,可以理解为xml
的<beans>
标签 -
@Bean
用来声明一个bean
,将其加入到Spring
容器中,可以理解为xml
的<bean>
标签
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>();
......
return redisTemplate;
}
}
2.2@Import
作用:将第三方jar包注入Spring,但是只可以作用在类上
例如在注解 EnableSpringConfigured
上就包含了 @Import
注解,用于将 配置文SpringConfiguredConfiguration
件加载进 Spring
容器。
@Import(SpringConfiguredConfiguration.class)
public @interface EnableSpringConfigured {}
当然,它里面value是一个数组可以注入多个class进容器
@Configuration
@Import(MyImportSelector.class)
public class MyConfig {}
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"org.springframework.demo.model.Teacher","org.springframework.demo.model.Student"};
}
}
其中 selectImports
方法返回的数组就会通过 @Import
注解注入到 Spring
容器中。
无独有偶,ImportBeanDefinitionRegistrar
接口也为我们提供了注入 bean
的方法
比如下面就注入了我们的Teacher到Spring容器中
@Configuration
@Import(value = {MyImportBeanDefinitionRegistrar.class})
public class MyConfig {}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata,
BeanDefinitionRegistry registry) {
RootBeanDefinition tDefinition = new RootBeanDefinition(Teacher.class);
// 注册 Bean,并指定bean的名称和类型
registry.registerBeanDefinition("teacher", tDefinition);
}
}
}
3.FactoryBean
说到FactoryBean,就想到了BeanFactory
BeanFactory:是IOC容器或者说对象工厂,管理所有Bean,是一个底层接口,ApplicationContext是它的子类,丰富了很多功能(国际化等等),并且BeanFactory是懒加载(要才有)
FactoryBean:它是一个Bean,是一个能够生产或者修饰对象的工程Bean,用了工厂模式和装饰器模式
3.1首先实现FactoryBean接口
public class TeacherFactoryBean implements FactoryBean<Teacher> {
/**
* 返回此工厂管理的对象实例
**/
@Override
public Teacher getObject() throws Exception {
return new Teacher();
}
/**
* 返回此 FactoryBean 创建的对象的类型
**/
@Override
public Class<?> getObjectType() {
return Teacher.class;
}
}
3.2然后通过@Configuration+@Bean的方式将TeacherFactoryBean加入容器中
@Configuration
public class MyConfig {
@Bean
public TeacherFactoryBean teacherFactoryBean(){
return new TeacherFactoryBean();
}
}
注意:我们没有向容器中注入 Teacher
,而是直接注入的 TeacherFactoryBean
,然后从容器中拿 Teacher
这个类型的 bean
,成功运行。
4.BeanFactoryPostProcessor
作用:是BeanFactory的后置处理器,方法postProcessBeanFactory对bean进行定义并且控制
这个registerBeanDefinition方法——>更好地使用接口来注入bean
实战:
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
/**
* 初始化过程中先执行
**/
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Teacher.class);
//Teacher 的定义注册到spring容器中
registry.registerBeanDefinition("teacher", rootBeanDefinition);
}
/**
* 初始化过程中后执行
**/
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
启动类代码
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
MyBeanDefinitionRegistryPostProcessor postProcessor = new MyBeanDefinitionRegistryPostProcessor();
// 将自定义实现类加入 Spring 容器
context.addBeanFactoryPostProcessor(postProcessor);
context.refresh();
Teacher bean = context.getBean(Teacher.class);
System.out.println(bean);
}
发现注入到Spring容器中
org.springframework.demo.model.Teacher@2473d930