Bean实例化的三种方式如何理解?

Bean实例化的三种方式

1,使用类构造器实例化(无参构造函数)
:直接通过Spring工厂返回类的实例对象
2,使用静态工厂方法实例化(简单工厂模式)
:Spring工厂调用自定义工厂的静态方法返回类的实例对象。
3,使用实例工厂方法实例化(工厂方法模式)
:Spring工厂调用工厂的普通方法(非静态方法)返回类的实例对象。

基于以上的三种方式,我们对比不使用Spring和使用Spring去实现对象的创建。

方式不使用Spring使用Spring
使用类构造器实例化(无参构造函数)通过手动调用无参构造方法创建对象通过Spring调用无参构造方法返回类的实例对象
使用静态工厂方法实例化(简单工厂模式)通过手动调用自定义工厂的静态方法返回对象的实例Spring工厂调用自定义工厂的静态方法返回类的实例对象。
使用实例工厂方法实例化 (工厂方法模式)通过手动调用自定义工厂的普通方法返回对象的实例Spring工厂调用工厂的普通方法(非静态方法)返回类的实例对象。

以上三种方式,先试试手动的形式创建对象。至于通过使用Spring去创建对象,无非是向Spring交代清楚该如何创建罢了。意思就是原本需要手动去做的,后来通过配置文件告诉Spring,这件事情就交给Spring你去做了。

JAVA原始表达:第一种方式:
创建Bean1

package demo3;


public class Bean1 {
    Bean1(){
        System.out.println("Bean1被实例化了");
    }
}

创建TestBean1

package demo3;

import org.junit.jupiter.api.Test;

public class TestBean1 {
    @Test
    public void test(){
        Bean1 bean1 = new Bean1();
    }
}

运行结果:
在这里插入图片描述
JAVA原始表达:第二种方式:
创建Bean2

package demo3;

public class Bean2 {
}

创建Bean2Factory工厂

package demo3;

public class Bean2Factory {
    public static  Bean2 getBean2(){
        System.out.println("通过自定义的静态方法返回Bean2实例");
        return new Bean2();
    }
}

创建TestBean2

package demo3;

import org.junit.jupiter.api.Test;

public class TestBean2 {
    @Test
    public void test(){
        Bean2 bean2 = Bean2Factory.getBean2();
    }
}

运行结果:
在这里插入图片描述
JAVA原始表达:第三种方式:
创建Bean3

package demo3;

public class Bean3 {
}

创建Bean3Factory工厂

package demo3;

public class Bean3Factory {
    public Bean3 getBean3(){
        System.out.println("通过自定义工厂的普通方法(非静态方法)返回Bean3的实例");
        return new Bean3();
    }
}

创建TestBean3

package demo3;

import org.junit.jupiter.api.Test;

public class TestBean3 {
    @Test
    public void test(){
        Bean3 bean3 = (new Bean3Factory()).getBean3();
    }
}

运行结果:
在这里插入图片描述
理解了上述逻辑之后,接下来看下Spring是如何实现的。

applicationContext.xml配置文件设置如下:

<?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="bean1" class="demo3.Bean1"></bean>
    <bean id="bean2" class="demo3.Bean2Factory" factory-method="getBean2"></bean>
    <bean id="bean3Factory" class="demo3.Bean3Factory"></bean>
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
</beans>

applicationContext.xml配置文件的设置:

<?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="bean1" class="demo3.Bean1"></bean>
    <!--第二种方式-->
    <bean id="bean2" class="demo3.Bean2Factory" factory-method="getBean2"></bean>
    <!--第三种方式-->
    <bean id="bean3Factory" class="demo3.Bean3Factory"></bean>
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
</beans>

主要是Test类的不同
Spring表达第一种方式: 使用类构造器实例化

package demo3;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean1 {
    /*普通情况获取对象的方式*/
    @Test
    public void test(){
        Bean1 bean1 = new Bean1();
    }
    /*通过Spring获取对象*/
    @Test
    public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean1 bean1 = (Bean1)applicationContext.getBean("bean1");
    }
}

Spring表达第二种方式 :使用静态工厂方法实例化

package demo3;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean2 {
    /*普通情况获取对象的方式*/
    @Test
    public void test(){
        Bean2 bean2 = Bean2Factory.getBean2();
    }
    /*通过Spring获取对象*/
    @Test
    public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean2 bean2 = (Bean2)applicationContext.getBean("bean2");
    }
}

Spring表达第三种方式 :实例工厂方法

package demo3;

import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBean3 {
    /*普通情况获取对象的方式*/
    @Test
    public void test(){
        Bean3 bean3 = (new Bean3Factory()).getBean3();
    }
    /*通过Spring获取对象*/
    @Test
    public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean3 bean3 = (Bean3)applicationContext.getBean("bean3");
    }
}

总结:
我们将三种方式测试方法摘出来对比:

/*Spring方式一的测试方法*/
public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean1 bean1 = (Bean1)applicationContext.getBean("bean1");
    }
/*Spring方式二的测试方法*/
public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean2 bean2 = (Bean2)applicationContext.getBean("bean2");
    }
}
/*Spring方式三的测试方法*/
public void springTest(){
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        Bean3 bean3 = (Bean3)applicationContext.getBean("bean3");
    }
}

无论使用何总方式,使用Spring的语法结构基本不变。getBean()是入口,指向的是bean标签的id,找到了id就可以找到对应的类进行对象的创建。
对比分析:

    <!--第一种方式-->
    <bean id="bean1" class="demo3.Bean1"></bean>
    <!--第二种方式-->
    <bean id="bean2" class="demo3.Bean2Factory" factory-method="getBean2"></bean>
    <!--第三种方式-->
    <bean id="bean3Factory" class="demo3.Bean3Factory"></bean>
    <bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
</beans>

拿第三种方式为例:
在这里插入图片描述

试推一下运行逻辑:
getBean(“bean3”)定位到bean标签属性id值为“bean3”的标签,此标签其factory-bean的属性指向包含自定义工厂的相关信息的bean标签,由此获取到了该工厂的实例对象,然后调用该实例对象的方法,得到Bean3的实例对象。一个bean标签返回一个bean实例。
我们知道,静态方法可以通过类名.方法名()去调用,而普通方法只能通过对象去访问,明确这一点,方式二和方式三的背后逻辑区别就清楚了。
在这里插入图片描述

  • 6
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jaywei.online

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值