Spring学习第2节 -- bean的scope和创建对象

Posted 积水成渊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring学习第2节 -- bean的scope和创建对象相关的知识,希望对你有一定的参考价值。

在xml配置文件中bean标签的属性中, 有几个比较重要的,第一个就是id, id是bean的唯一标识, class属性是bean的类全名 scope用来标识bean的作用域

Bean scope属性

scope的默认值是singleton, singleton是单例
如果想要获得一个普通对象, 可以使用prototype作为scope的值, scope还有其他的 request, session, global session, 顾名思义就好了, spring还支持自定义scope
singleton和prototype对象的创建时间
singleton默认在初始化容器时创建, 而prototype在需要的时候,才进行对象的创建, 如果想要改变singleton Bean对象的创建时间, 可以在bean标签添加一个属性. 
property或者constructor-arg的ref属性可以引用另一个bean 通过id
lazy-init="true" 

无参构造

<!-- more bean definitions go here -->
<bean id="userWithoutConstrutor" class="io.github.coinsjack.pojo.User" scope="prototype" lazy-init="true" >
</bean>
有参构造
<bean id="userWithConstrutor" class="io.github.coinsjack.pojo.User" scope="prototype" lazy-init="true" >
<constructor-arg type="java.lang.Integer" value="10010"/>
<constructor-arg type="java.lang.String" value="jack"/>
<constructor-arg type="java.lang.String" value="你飘了啊"/>
</bean>

使用SETTER来创建

<bean id="userUseSetter" class="io.github.coinsjack.pojo.User" scope="prototype" lazy-init="true" >
<property name="id" value="10010"/>
<property name="name" value="setter name"/>
<property name="phone" value="18234508888"/>
</bean>

测试

public static void main(String[] args) {

// container
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("initialize container");
// get a bean
User jackyuserWithConstrutor = (User) applicationContext.getBean("userWithConstrutor");
System.out.println(jackyuserWithConstrutor);

User userWithoutConstrutor = (User) applicationContext.getBean("userWithoutConstrutor");
System.out.println(userWithoutConstrutor);

User userUseSetter = (User) applicationContext.getBean("userUseSetter");
System.out.println(userUseSetter);

// destroy container
((ClassPathXmlApplicationContext)applicationContext).destroy();
}
}

结果

initialize container
User{id=10010, name=‘jack‘, phone=‘你飘了啊‘}
User{id=null, name=‘null‘, phone=‘null‘}
User{id=10010, name=‘setter name‘, phone=‘18234508888‘}

对setter的研究, 如果成员变量名称和setter之间没有规律的命名,那么还可以正确创建吗?

setter
public void setname(String name) {
this.strangeName = name;
}
bean
<bean id="userUseSetter" class="io.github.coinsjack.pojo.User" scope="prototype" lazy-init="true" >
<property name="id" value="10010"/>
<property name="strangeName" value="setter name"/>
<property name="phone" value="18234508888"/>
</bean>
结果
Bean property ‘strangeName‘ is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
事实上这也正常, spring并不是足够聪明能够忍受你的调戏., 所以正常的写代码就好了, 事实上成员变量为filedName的setter方法名为setfiledName也可以, 而不用管是不是严格的小驼峰
 

工厂类成员函数构造

工厂类
package io.github.coinsjack.pojo;

public class UserFactory {

public static User getUserStatic() {
return new User(10010, "static way user", "10010");
}

public User getUser() {
return new User(10011, "normal method user", "10000");
}
}

静态函数构造和非静态函数构造

Bean配置
<!--工厂Bean-->
<bean id="userFactory" class="io.github.coinsjack.pojo.UserFactory" />
<!--使用工厂Bean的非静态方法-->
<bean id="userByFactoryNonStatic" factory-bean="userFactory" factory-method="getUser" >
</bean>

<!--使用工厂Bean的静态方法-->
<!-- class指明工厂类的类型 -->
<bean id="userByFactoryStatic" class="io.github.coinsjack.pojo.UserFactory" factory-method="getUserStatic" >
</bean>
使用
template = "---%s%n%s%n";
User userByFactoryNonStatic = (User) applicationContext.getBean("userByFactoryNonStatic");
System.out.printf(template, "userByFactoryNonStatic", userByFactoryNonStatic);

template = "---%s%n%s%n";
User userByFactoryStatic = (User) applicationContext.getBean("userByFactoryStatic");
System.out.printf(template, "userByFactoryStatic", userByFactoryStatic);
template的声明在前面. 看似是多余的, 但其实有时候需要改变template的内容, 所以就容忍多这么一点"开销"吧
结果
---userByFactoryNonStatic
User{id=10011, name=‘normal method user‘, phone=‘10000‘}
---userByFactoryStatic
User{id=10010, name=‘static way user‘, phone=‘10010‘}
 
扩展测试, 如果工厂构造方法要求一个参数
UserFactory
public static User getUserStatic(int id, String name, String phone) {
return new User(10010, "static way user", "10010");
}

public User getUser(int id, String name, String phone) {
return new User(10011, "normal method user", "10000");
}
配置
<!--使用工厂Bean的需要参数的非静态方法-->
<bean id="userFactoryNeedArg" factory-bean="userFactory" factory-method="getUser" >
<property name="id" value="100"/>
<property name="name" value="需要参数的工厂构造非静态方法"/>
<property name="phone" value="NULL"/>
</bean>
使用
template = "---%s%n%s%n";
User userFactoryNeedArg = (User) applicationContext.getBean("userFactoryNeedArg");
System.out.printf(template, "userFactoryNeedArg", userFactoryNeedArg);
结果
 
---userFactoryNeedArg
User{id=100, name=‘需要参数的工厂构造非静态方法‘, phone=‘NULL‘}

以上是关于Spring学习第2节 -- bean的scope和创建对象的主要内容,如果未能解决你的问题,请参考以下文章

第65节:Java后端的学习之Spring基础

Spring注解基础学习总结

spring学习-IOC-scope作用域

Spring-IOC学习笔记-05bean的属性

Spring之Bean的作用域与生命周期

Spring学习笔记2 - Bean