ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring Bean的实例化

2021-05-02 09:33:33  阅读:174  来源: 互联网

标签:name Spring age factory Bean 实例 Person1


Spring Bean的实例化

在Spring中Bean的实例化由三种

  1. 构造器实例化
  2. 静态工厂方式实例化
  3. 实例化工厂方式实例化

创建一个实体类Person1

public class Person1 {
    
    private String name;
    private int age;
    private String sex;

    public Person1(int age, String sex) {
        this.age = age;
        this.sex = sex;
    }

    public Person1(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person1(String name, int age, String sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
    }

    public Person1() {
        System.out.println("我是无参构造器");
    }

    @Override
    public String toString() {
        return "Person1{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }

构造器实例化

使用该类的默认构造器(无参构造器)实例化Bean
配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="person" class="com.lyl.testBean.Person1"/>

</beans>

测试类:

 public static void main(String[] args) {
        // 初始化Spring容器,加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");

        System.out.println(context.getBean("person");
    }

打印结果:

com.lyl.testBean.Person1@50f8360d

这个应该是最直接的,也是最简单的实例化Bean了(在Spring中)。


有参构造器
配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="person" class="com.lyl.testBean.Person1">
      <constructor-arg index="0" name="name" type="java.lang.String" value="张三"/>
      <constructor-arg index="1" name="age" type="int" value="6"/>
   </bean>

   <bean id="person2" class="com.lyl.testBean.Person1">
      <constructor-arg index="1" name="sex" type="java.lang.String" value="赵六"/>
      <constructor-arg index="0" name="age" type="int" value="18"/>
   </bean>

   <bean id="person3" class="com.lyl.testBean.Person1">
         <constructor-arg index="0" name="name" type="java.lang.String" value="李四"/>
         <constructor-arg index="1" name="age" type="int" value="18"/>
         <constructor-arg index="2" name="sex" type="java.lang.String" value="男"/>
   </bean>

   <bean id="person4" class="com.lyl.testBean.Person1">
         <constructor-arg index="0" name="name" type="java.lang.String" value="6"/>
         <constructor-arg index="1" name="age" type="int" value="16"/>
   </bean>

</beans>

测试类:

 public static void main(String[] args) {
        // 初始化Spring容器,加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext1.xml");

         System.out.println(context.getBean("person"));
        System.out.println(context.getBean("person2"));
        System.out.println(context.getBean("person3"));
        System.out.println(context.getBean("person4"));
    }

打印结果:

Person1{name='张三', age=6, sex='null'}
Person1{name='null', age=18, sex='赵六'}
Person1{name='李四', age=18, sex='男'}
Person1{name='6', age=16, sex='null'}

<constructor-arg index="0" name="name" type="java.lang.String" value="张三"/>
<constructor-age></constructor-age>标签意为一个参数,构造函数中有几个参数就有几个此标签
index属性:俗称角标,参数的顺序,从0代表构造函数中第一个形式参数
name属性:俗称形参名,参数的形参名,这个属性要在有参构造函数中保持和index相对应的形参名,如果不一样,则会报错!
type属性:数据类型,需要写全限定类名!
value属性:实参,需要与对应的type中的数据类型保持一致,否则会报错!

静态工厂方式实例化

创建静态工厂类:

// 静态工厂类
public class MyStaticBeanFactory {
    // 创建Bean实例化的工厂方法
    public static Person1 createPerson1(){
        return new Person1();
    }
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
   <!-- class指向的是静态工厂类的全限定类名,factory-method指向的是调用静态工厂类的createPerson1()方法获取Bean实例 -->
   <bean id="person" class="com.lyl.testBean.MyStaticBeanFactory" factory-method="createPerson1"/>

</beans>

测试类:

 public static void main(String[] args) {
        // 初始化Spring容器,加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext2.xml");
       
        System.out.println(context.getBean("person"));
    }

打印结果:

com.lyl.testBean.Person1@174d20a

定义了id为person的Bean,class指定的是静态工厂类的全限定类名,而factory-method是通知Spring容器调用静态工厂类的createPerson1()方法的带Bean的实例。

可能看起来稍微难理解一点点,其实就是本质就是调用了静态工厂的createPerson1()方法,而Bean是什么?Bean说到底了了也是一个Java类,Spring在期间只是调用了方法而已,如果有返回值便会把返回值传递给Bean,那么工厂的静态方法如果没有返回值怎么办?会报错!

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'person' defined in class path resource [applicationContext2.xml]: Invalid factory method 'createPerson1': needs to have a non-void return type!

线程“main”org.springframework.beans.factory.bencreationException中出现异常:创建在类路径资源[applicationContext2.xml]中定义的名为“person”的bean时出错:无效的工厂方法“createPerson1”:需要具有非空返回类型!

可以看到Spring不允许没有返回值,也就是该方法必须要有返回值!修饰词不能为void

实例化工厂方式实例化

创建实例化工厂类:

public class MyBeanFactory {
    MyBeanFactory(){
        System.out.println("person1工厂实例化中。。。");
    }
    
    public Person1 createPerson1(){
        return new Person1();
    }
}

配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

   <bean id="myFactory" class="com.lyl.testBean.MyBeanFactory"/>
   
   <bean id="person" factory-bean="myFactory" factory-method="createPerson1"/>

</beans>

测试类:

  public static void main(String[] args) {
        // 初始化Spring容器,加载配置文件
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext3.xml");

        System.out.println(context.getBean("person"));
    }

打印结果:

person1工厂实例化中。。。

com.lyl.testBean.Person1@174d20a

这个看起来就比静态工厂类实例化Bean更复杂一点了,那么我们不妨单独提出来看看。

先看实例化工厂类:

我们知道在工厂类中想得到Person1类的对象只能调用createPerson1()方法,而这个方法又不是上面的静态方法,所以我们还需要得到工厂类的实例才能调用方法。OK!那么我们就知道了得到Person1类的对象需要先创建实例化工厂类的对象。

再看看配置文件:

id为myFactory的Bean,class指定的是实例化工厂类的全限定类名,干嘛的?是不是有点像构造方法实例化Bean?

id为person的Bean多了两个属性(factory-bean、factory-method)少了常见的class属性。

那么再看测试类:

与之前两个获取Bean方法的测试类没有区别,说明我们在测试类中视觉上是加载了id为person的Bean,但是再看配置文件中为person的Bean并没有class指定的全限定类名,反而多了factory-bean这个属性。

factory-bean——工厂(顾名思义,factory-bean就是生成bean的工厂对象,factory-bean属性和factory-method属性一起使用,首先要创建生成bean的工厂类和方法。)

那么最终是怎么得到Person1类对象的呢?
通知Spring加载id为person的Bean,检查到有factory-bean属性和factory-method属性,又去查找id为factory-bean中的值(myFactory)的Bean并根据class属性初始化,再根据factory-method属性中的值的方法去工厂类中调用并传递返回值。这就是我理解的实例化工厂类实例化Bean的过程。我理解的肯定不是完全正确的,但是至少能帮助我们前期理解其中的表层运行过程,后面肯定是需要我们运用到实际项目中去实践,再去总结。

注意:

Q: 在借助Spring容器创建Bean时,对象是在调用getBean("xxx")方法之前创建还是调用时创建?
A:在ApplicationContext加载配置文件时,Spring容器会自动创建配置文件中的Bean,并保存,而getBean()方法其实是在Spring容器中得到对象。这个问题在使用构造方法创建对象就可以发现,比如在无参构造器输出“ 我是无参构造器,我被创建了!”,测试类中不写getBean()方法,只加载配置文件,控制台就会打印出无参构造器的输出语句,证明了Bean对象创建在加载配置文件时,而不是调用getBean方法时。
Q:有了有参构造器是不是创建对象比setter注入方便
A:这个有根据实际业务情况,setter注入更加普遍通用,也更加灵活,而有参构造器,虽然方便一点,但是也有缺点,那就是该类中必须要有与之对应的构造方法!如果没有,则不能通过该方法创建对象。

标签:name,Spring,age,factory,Bean,实例,Person1
来源: https://www.cnblogs.com/cndada/p/14721211.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有