Spring学习-IOC容器怎样创建对象

1.IOC容器创建对象的原理

        我们知道Spring创建对象是在xml文件中使用bean标签创建的,当我们获取上下文对象时就会被创建(下面会讲到),那么为什么Spring使用bean标签就能创建一个对象呢?

        通常我们在new一个对象时会调用这个类的构造器,即使我们在编写一个类时不写构造方法,系统也会生成一个默认的无参构造方法,这个无参构造方法实际上继承的是万类之父Object的无参构造方法,所以即使我们不写构造函数也能直接new创建。那么当我们写了自己的无参构造方法后,new一个对象就会调用我们自己写的无参构造方法,这就是重写构造函数。

        既然new是调用的构造器来创建,那么bean标签是不是也是通过调用的构造器来创建对象呢?我们来做一个实验,使用bean标签创建一个User对象:

        先定义一个User类:

public class User {
    
    private String name;
    private int age;
    
    //重写无参构造,如果调用了无参构造就会输出“调用了构造函数”
    public User() {
        System.out.println("调用了构造函数");
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }
}

        然后通过bean标签创建一个user对象:

    <!--创建一个User类对象,并给name和age属性赋值-->
    <bean id="user" class="com.anzekun.pojo.User">
        <property name="name" value="zhangsan"/>
        <property name="age" value="20"/>
    </bean>

        最后通过使用getBean方法让Spring开始创建来测试是否调用了重写的构造方法:

public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        User user= (User) context.getBean("user");
    }

        运行结果:

        由此可见,Spring容器使用bean标签来创建对象,实际上是调用了构造器创建的,这就是IOC容器创建对象的原理。

2.使用bean标签实现有参构造

        上面我们使用的是无参构造方法,并利用set方法给user的属性赋值(property标签给属性赋值就是调用的set方法,即使用set方法进行依赖注入),那么怎样进行有参构造呢?Spring也为我们提供了有参构造的bean标签创建对象的方法,并且有三种:

        先写一个有参构造器:

//有参构造
    public User(String name,int age){
        this.name=name;
        this.age=age;
    }

        测试:

public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        User user= (User) context.getBean("user");
        System.out.println("name:"+user.getName());
        System.out.println("age:"+user.getAge());
    }
  •  第一种,使用下标赋值
    <!--利用下标赋值-->
    <bean id="user" class="com.anzekun.pojo.User">
        <!--0代表第一个参数,1代表第二个参数-->
        <constructor-arg index="0" value="zhangsan"/>
        <constructor-arg index="1" value="15"/>
    </bean>

        运行结果:

  • 第二种,使用参数类型赋值
    <!--使用参数类型赋值-->
    <bean id="user" class="com.anzekun.pojo.User">
        <constructor-arg type="java.lang.String" value="lisi"/>
        <constructor-arg type="int" value="20"/>
    </bean>

        运行结果:

        不过要注意的是,由于这种方法是利用参数类型区分参数的,所以如果有多个相同类型的参数不建议使用这种方法

  • 第三种,使用参数名赋值
    <!--使用参数名赋值-->
    <bean id="user" class="com.anzekun.pojo.User">
        <constructor-arg name="name" value="wangwu"/>
        <constructor-arg name="age" value="19"/>
    </bean>

        运行结果:

3.IOC容器创建对象是一次创建所有对象还是用到哪个才创建哪个?

        我们先获取两个对象,观察是否调用了构造函数:

    <!--创建两个对象-->
    <bean id="user" class="com.anzekun.pojo.User">
        <property name="name" value="zhangsan"/>
        <property name="age" value="20"/>
    </bean>
    <bean id="user1" class="com.anzekun.pojo.User">
        <property name="name" value="lisi"/>
        <property name="age" value="15"/>
    </bean>

        使用之前的无参构造函数进行测试,如果调用了构造函数就输出“调用了构造函数”:

       

    public static void main(String[] args) {
        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        System.out.println("获取第一个对象");
        User user= (User) context.getBean("user");
        System.out.println("获取第二个对象");
        User user1=(User) context.getBean("user1");
    }

        运行结果:

        从运行结果可以看出,我们在获取对象之前就调用了两次构造函数,这就说明当我们在获得Spring的上下文对象时Spring就已经创建好了所有的对象,后面我们获取的时候直接拿就行了,这也就是为什么叫做容器的原因了

4.如果两次获取同一个id的对象,这两个对象是否是同一个对象?

        上面我们进行的测试结果是先创建所有的对象,后面获取时不会再创建,对于这个问题我们大致也能猜到这两个是同一个对象了,来看测试:

        ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
        //两次获取同一个id对象
        User user= (User) context.getBean("user");
        User user1= (User) context.getBean("user");
        //输出比较结果
        System.out.println(user1==user);

        运行结果:

        所以同一个id的对象Spring只会创建一个,每次获取的都是同一个对象

  • 14
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值