您的位置:

Spring创建Bean的三种方式

在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中