实例化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, 抽象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作为模板特别好