在Spring中,Bean是一个由Spring IoC容器创建、管理、调用的Java对象。Spring创建Bean有三种方式,它们分别是基于XML配置文件创建、基于注解创建和基于Java配置类创建。本文将从多个方面详细阐述这三种方式。
一、创建Bean的三种方式
1.1 基于XML配置文件创建
基于XML配置文件创建Bean是最经典的方式。它的主要流程是:先通过
标签在XML配置文件中定义Bean的基本信息,如ID、Class、scope等,然后通过
标签对Bean的属性进行初始化。例如以下示例:
<bean id="student" class="com.example.Student">
<property name="name" value="张三"/>
<property name="age" value="18"/>
</bean>
上述配置文件中定义了一个名为"student"的Bean,它的Class为"com.example.Student",scope默认为singleton(单例),并且在初始化时会设置它的name和age属性。
1.2 基于注解创建
基于注解创建Bean是Spring 2.5版本后引入的一种方式。通过在Java类上添加注解,告诉Spring IoC容器该类是一个Bean,同时指定Bean的ID、Class等信息。例如:
@Component("student")
public class Student {
private String name;
private int age;
// getters and setters
}
上述代码中,@Component注解表示该类是一个Bean,并且指定了它的ID为"student"。Spring在扫描到该注解后,会自动注册该Bean到IoC容器中。
1.3 基于Java配置类创建
基于Java配置类创建Bean是在Spring 3.0版本后引入的。它使用Java类代替XML配置文件,通过Java代码的方式来创建和配置Bean。例如:
@Configuration
public class AppConfig {
@Bean
public Student student() {
Student student = new Student();
student.setName("张三");
student.setAge(18);
return student;
}
}
上述代码中,@Configuration注解表示该类是一个Java配置类,@Bean注解表示要创建一个Bean,并且指定了该Bean的Class为Student。然后通过创建Student对象并设置属性,最后返回该对象来完成Bean的创建。
二、Spring注入Bean的三种方式
2.1 Setter方法注入
Setter方法注入是指通过在Bean类中创建Setter方法,然后在XML配置文件或Java配置类中将依赖的Bean注入到改方法中进行设置。例如:
public class Teacher {
private Student student;
public void setStudent(Student student) {
this.student = student;
}
// other methods
}
<bean id="teacher" class="com.example.Teacher">
<property name="student" ref="student"/>
</bean>
上述代码中,Teacher依赖于Student,通过
标签将Student注入到Teacher类的setStudent()方法中进行设置。
2.2 构造方法注入
构造方法注入是指通过在Bean类中创建构造方法,然后在XML配置文件或Java配置类中将依赖的Bean通过构造方法的参数进行设置。例如:
public class Teacher {
private Student student;
public Teacher(Student student) {
this.student = student;
}
// other methods
}
<bean id="teacher" class="com.example.Teacher">
<constructor-arg ref="student"/>
</bean>
上述代码中,Teacher依赖于Student,通过
标签将Student注入到Teacher类的构造方法中进行设置。
2.3 字段注入
字段注入是指通过在Bean类中创建字段,并且在XML配置文件或Java配置类中将依赖的Bean直接注入到该字段上进行设置。例如:
public class Teacher {
@Autowired
private Student student;
// other methods
}
<bean id="teacher" class="com.example.Teacher"/>
上述代码中,@Autowired注解表示要将依赖的Bean注入到该字段上,Spring IoC容器会自动将Student注入到Teacher类的student字段中进行设置。
三、Spring创建Bean的过程
Spring创建Bean的过程包括了Bean的实例化、Bean的属性注入、Bean的初始化和Bean的销毁过程。其中Bean的实例化是通过Java反射机制或工厂方法来创建Bean实例的;Bean的属性注入是通过Setter方法或字段注入来设置Bean的属性值的;Bean的初始化是通过实现InitializingBean接口或定义init-method方法来完成的;Bean的销毁是通过实现DisposableBean接口或定义destroy-method方法来完成的。 以下是完整的创建Bean的过程代码示例:
public class Student implements InitializingBean, DisposableBean {
private String name;
private int age;
public Student() {
System.out.println("Bean实例化");
}
public void setName(String name) {
this.name = name;
System.out.println("Setter方法注入");
}
public void setAge(int age) {
this.age = age;
System.out.println("Setter方法注入");
}
public void afterPropertiesSet() throws Exception {
System.out.println("Bean初始化");
}
public void destroy() throws Exception {
System.out.println("Bean销毁");
}
// other methods
}
<bean id="student" class="com.example.Student" init-method="afterPropertiesSet" destroy-method="destroy">
<property name="name" value="张三"/>
<property name="age" value="18"/>
</bean>
上述代码中,Bean的实例化和属性注入放在了构造方法和Setter方法中实现,同时实现了InitializingBean接口和DisposableBean接口的方法来完成Bean的初始化和销毁过程,并且通过init-method和destroy-method属性指定了初始化和销毁的方法。
四、Spring管理Bean的两种方式
Spring管理Bean的方式有两种,分别是单例模式和原型模式。单例模式是指在整个应用程序中只存在一个Bean实例;原型模式是指每次通过IoC容器获取Bean实例时都会创建一个新的实例。
4.1 单例模式
单例模式是Spring默认的Bean管理方式,它保证在整个应用程序中只存在一个Bean实例。在XML配置文件或Java配置类中将Bean的scope属性设置为singleton或省略scope属性即可使用单例模式。例如:
<bean id="student" class="com.example.Student" scope="singleton">
<property name="name" value="张三"/>
<property name="age" value="18"/>
</bean>
上述代码中,Bean的scope属性设置为singleton,表示使用单例模式来管理Bean。
4.2 原型模式
原型模式是指每次通过IoC容器获取Bean实例时都会创建一个新的实例。在XML配置文件或Java配置类中将Bean的scope属性设置为prototype即可使用原型模式。例如:
<bean id="student" class="com.example.Student" scope="prototype">
<property name="name" value="张三"/>
<property name="age" value="18"/>
</bean>
上述代码中,Bean的scope属性设置为prototype,表示使用原型模式来管理Bean。
五、Spring创建Bean的方法
在Spring中,除了通过
标签、@Component注解和Java配置类来创建Bean外,还可以通过FactoryBean和BeanDefinitionRegistry接口来创建Bean。
5.1 FactoryBean创建Bean
FactoryBean是一个特殊的Bean,它可以通过用户自定义的逻辑来创建其他Bean实例。FactoryBean接口定义了getObject()方法,该方法返回一个Object类型的Bean实例。例如:
public class MyFactoryBean implements FactoryBean<Student> {
@Override
public Student getObject() throws Exception {
Student student = new Student();
student.setName("张三");
student.setAge(18);
return student;
}
@Override
public Class<? extends Student> getObjectType() {
return Student.class;
}
@Override
public boolean isSingleton() {
return true;
}
}
<bean id="myFactoryBean" class="com.example.MyFactoryBean"/>
<bean id="student" factory-bean="myFactoryBean" factory-method="getObject"/>
上述代码中,MyFactoryBean实现了FactoryBean接口,并且通过getObject()方法来创建一个Student实例。然后在XML配置文件中,将myFactoryBean定义为Bean,并且在student Bean中使用factory-bean和factory-method属性来指定由myFactoryBean来创建Student实例。
5.2 BeanDefinitionRegistry接口创建Bean
BeanDefinitionRegistry接口是Spring IoC容器中的一个扩展接口,它可以通过编码方式来创建Bean定义,并注册到IoC容器中。例如:
public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
RootBeanDefinition beanDefinition = new RootBeanDefinition(Student.class);
beanDefinition.getPropertyValues().add("name", "张三");
beanDefinition.getPropertyValues().add("age", 18);
registry.registerBeanDefinition("student", beanDefinition);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// do nothing
}
}
<bean class="com.example.MyBeanDefinitionRegistry"/>
上述代码中,MyBeanDefinitionRegistry实现了BeanDefinitionRegistryPostProcessor接口,并在postProcessBeanDefinitionRegistry()方法中,通过RootBeanDefinition来创建Student实例,并且通过registerBeanDefinition()方法将该实例的Bean定义注册到IoC容器中。
六、Spring创建对象的三种方式
在Spring中,除了创建Bean外,还可以使用三种方式来创建对象,它们是new关键字、Spring上下文和Spring工厂方法。
6.1 new关键字创建对象
使用new关键字创建对象是最传统的方式,它通过Java类的构造方法来创建对象。例如:
Student student = new Student();
student.setName("张三");
student.setAge(18);
上述代码中,使用new关键字创建一个Student对象。
6.2 Spring上下文创建对象
使用Spring上下文创建对象是指在Spring IoC容器中获取Bean实例,然后通过getType()方法获取它的Class类型,并通过反射机制来创建该类的实例。例如:
AbstractApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
Student student = context.getBean("student", Student.class);
上述代码中,通过ClassPathXmlApplicationContext()方法来创建一个Spring上下文,并通过getBean()方法来获取名为"Student"的Bean实例,并通过Student.class类型来创建该类的实例。
6.3 Spring工厂方法创建对象
使用Spring工厂方法创建对象是指在Spring IoC容器中通过工厂方法来创建对象。例如:
public class MyFactory {
public Student createStudent() {
Student student = new Student();
student.setName("张三");
student.setAge(18);
return student;
}
}
<bean id="myFactory" class="com.example.MyFactory"/>
<bean id="student" factory-bean="myFactory" factory-method="createStudent"/>
上述代码中,MyFactory类定义了一个createStudent()方法,该方法通过new关键字来创建Student实例,并设置它的属性。然后再XML配置文件中,将myFactory定义为Bean,并通过factory-bean和factory-method属性来指定由myFactory来创建Student实例。
七、Bean在Spring中