实例化bean的三种方式

 

第一种: 使用无参构造函数(重点第一种,二三种已经没太多人用了)

 

 

hi是一个简单的bean , 只有println();

<bean id="binbin" class="test_one.hi"></bean>

id 是唯一标识, class是类路径(src/main/java是默认路径,不可更改,所以必须在该目录下添加包,并且为了能找到该类,该类需要在头上加package,很显然两者是对应的)

scope: 指定对象作用范围  singleton : 默认值,单例模式(只要被实例化,该实例就会一直存活,除非容器销毁或退出,并且IoC容器只存在一个实例,所有对该对象的引用将共享这个实例) prototype: 多例模式(每次请求都将创建一个新的实例,当实例长时间不用会被java的垃圾回收机制回收)

request, session, global session 这三种只适用于web应用程序,通常是与XmlWebApplicationContext共同使用

单例模式:

 

 多例模式:

 

 如果创建一个新的实例classpathxmlapplicationcontext, 他们之间的地址是不一样的,由于ApplicationContext是继承BeanFactory,所以我们可以说

在同一个容器内,单例模式下的实例为同一实例,在同一容器内访问该实例为同一实例,引用对象共享实例

 

 

从上面的singleton模式我们就能明白,为什么一个实例可以一直存在并且对该对象的引用都共享这个实例. 如果这个实例要不一样的属性呢?

bean就是可复用的类, 因为有的类每次我们实例化就只要用里面的函数,  不需要将实例当作数据一样对待..而bean的出现就解决了繁琐地创建实例以及浪费内存资源

那为什么是无参构造函数呢? 因为可复用类不能用有参构造函数

 

下面是如何从配置文件中获得实例化bean

可以看出,我们通过bean.xml文件,通过getBean(唯一标识id)得到我们想要的对象,而不用我们主动去创建对象,这就是典型的工厂模式。 getBean是BeanFactory接口的方法,返回得对应id的实例。

 

 

第二种 :使用静态工厂创建

bean.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="binbin" class="test_one.hi"></bean>
<!--使用静态工厂实例化-->
<bean id="static" class="test_one.static_test" factory-method="sayStatic"></bean>

</beans>

id 唯一标识; class 类路径;   factory-method 工厂方法名

static_test类

 

 

如何通过静态工厂得到实例

 

 第一种是直接从配置文件bean.xml得到实例,而第二种是从配置文件bean.xml寻找对应的静态方法,再从静态方法返回实例。

那么静态工厂是单例模式吗? 就是每次调用的时候不会创建新的实例,会共享实例。

在spring中默认是单例模式, 不在spring是多例

下图为不在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="binbin" class="test_one.hi" scope="prototype"></bean>
<!--使用静态工厂实例化-->
<bean id="static" class="test_one.static_test" factory-method="sayStatic"></bean>
<!--使用实例工厂实例化-->
<bean id="instance" class="test_one.instance"></bean>
<bean id="createInstance" factory-bean="instance" factory-method="createHi"></bean>
</beans>

instance.java

 

 

 

得到实例化

 

 第三种有点复杂

静态工厂模式和实例模式都会多实例化一个对象,也就是静态方法或者方法所在的类

以上三种实例化bean的方法, 在程序开始运行后就已经实例化了, 如果在bean中加入构造函数就会发现哪怕没有获取实例化也执行了构造函数, 这就说明开始就已经实例化了

 参考:

Bean的3种实例化

Bean的3种实例化

非实例化bean, 抽象bean:

abstract属性为true,表示该bean为抽象bean,不会被实例化,但是其属性可以注入到其它bean中

抽象bean的一个好处就是做模板 , 如果两个类有相同的属性,那么可以注入抽象bean来解决通过两次重复操作来注入该属性

abstract="true"

//两个有相同属性的类(不用声明父类)
public class FooDao {
    private DataSource dataSource;
    private SomeHelper someHelper;
    private FooHelper fooHelper;
 
    //setters
}
public class BarDao {
    private DataSource dataSource;
    private SomeHelper someHelper;
    private BarHelper barHelper;
 
    //setters
}
//xml定义抽象bean(并不会实例化这个bean)
<bean id="dao" abstract="true"> <!--实际根本没有这个类-->
    <property name="dataSource" ref="dataSource"/>
    <property name="someHelper" ref="someHelper"/>
</bean>
 
 <!--指定parent为dao,则只需要再注入自己特别的属性即可-->
<bean id="fooDao" class="FooDao" parent="dao">
    <property name="fooHelper" ref="fooHelper" />
</bean>
<bean id="barDao" class="BarDao" parent="dao">
    <property name="barHelper" ref="barHelper" />
</bean>

抽象bean不是指抽象类,其实根本就没有这个类

抽象bean的属性在子bean一定是拥有的, 如果没有就会报错

如果子bean注入了数据, 那么取得是子bean的值

如果有多个bean有相同的属性并且值也相同(个别bean不同) , 那么可以用抽象bean来注入相同的属性, 并且还不影响个别子bean的值不同

所以抽象bean作为模板特别好

posted @ 2022-02-24 17:45  binbin_cloud  阅读(1335)  评论(0编辑  收藏  举报