8. bean的创建模式
# spring工厂的相关特性
注意:工厂默认在管理对象时都是单例方式,单例方式无论在工厂中获取多少次始终获取的是同一个对象
1.spring中工厂创建对象的模式
1). 默认spring在管理组件对象时是 单例创建 singleton
service dao 单例形式管理
2). 如何修改工厂创建组件对象为多例
structs2 action 必须以多例形式管理
spring工厂在管理对象时默认使用的是单例模式
修改spring工厂创建对象的模式为多例模式
bean标签有一个scope属性,如果不写这个属性则默认scope值是singleton,也就是单例模式,如果在scope属性中写入prototype,代表创建对象的模式为多例。
<!--配置文件中-->
<!--管理DAO组件
scope:用来指定工厂创建对象的模式
默认值:singleton 单例
prototype 多例
-->
<bean class="scope.TagDAOImpl" id="tagDAO" scope="prototype"></bean>
修改创建对象的方式为多例的测试结果:
9. bean的生产原理
# spring工厂创建对象的原理
原理:反射 + 构造方法
// 工厂原理
TagDAO tt = (TagDAO) Class.forName("scope.TagDAOImpl").newInstance();
System.out.println(tt);
反射 + 构造方法 创建对象的测试结果
10. bean的生命周期
# spring工厂管理组件生命周期
1.组件对象什么时候创建 2.组件对象什么时候销毁
单例对象:工厂启动工厂中所有的单例的对象随之创建,工厂销毁工厂中所有单例对象随之销毁
多例对象:每次在工厂中使用时进行创建 工厂不负责多例对象的销毁
对于单例模式和多例模式的对象来说spring中管理对象的生命周期也是不同的。
小知识
-
bean标签内部有一个init-method属性,代表在对象初始化时需要调用的方法,如果希望调用方法名为init2001的方法,就使
init-method=“init2001”;bean标签内部还有一个destroy-method属性,代表在对象销毁时需要调用的方法,如果希望调用
方法名为destory的方法,就使destroy-method=“destory”。
注意:init-method和destroy-method所调用的方法必须是在当前bean标签所代表的类中有的方法。
10.1 对于单例模式创建的对象的生命周期的管理
需要用到的TageDAO组件的实现类TagDAOImpl
public class TagDAOImpl implements TagDAO{
@Override
public void save(String name) {
System.out.println("DAO Name:" + name);
}
// init
public void init2001(){
System.out.println("组件对象初始化");
}
// destory
public void destory(){
System.out.println("组件对象销毁");
}
}
配置文件
<!--管理DAO组件
scope:用来指定工厂创建对象的模式
默认值:singleton 单例
prototype 多例
生命周期方法:
init-method="" 在对象初始化时调用的方法
destroy-method="" 在对象销毁时调用的方法
-->
<bean class="scope.TagDAOImpl" id="tagDAO" init-method="init2001" destroy-method="destory"></bean>
测试和结果
单例对象什么时候去创建呢?
- 单例对象是在工厂启动的时候创建还是在获得的时候创建还是在真正使用的时候去创建呢?
在上面的代码中只有工厂的启动,却还是执行了只有在初始化对象时才执行的init2001方法(init2001方法打印出"组件对象初始化"这句话)。所以我们可以得出结论:单例模式创建的对象在spring工厂启动时就被创建了。
补充
另外我们可能会疑惑,为什么没有执行对象销毁时调用的destory方法呢,这是因为只有在工厂正常关闭时才会调用destory方法,而上面代码线程停止(相当于断电了),工厂没有正常关闭,也就不会调用destory方法了。
还有:工厂的关闭方法close()方法只有在实现类中才有,在工厂抽象类中没有,因此如果我们想要调用close()方法,还必须把抽象工厂接口强转为实现类(联系多态,只有父类有的方法使用父类对象才可以调用),在强转时需要使用两个括号。
正常关闭工厂的测试结果:
10.2 对于多例模式创建的对象的生命周期的管理
配置文件
因为是多例模式,所以bean标签的scope属性需要写prototype
<!--管理DAO组件
scope:用来指定工厂创建对象的模式
默认值:singleton 单例
prototype 多例
生命周期方法:
init-method="" 在对象初始化时调用的方法
destroy-method="" 在对象销毁时调用的方法
-->
<bean class="scope.TagDAOImpl" id="tagDAO" scope="prototype" init-method="init2001" destroy-method="destory"></bean>
测试和结果
11. bean工厂创建对象的好处
# spring工厂好处
1. 解耦合 使用配置文件管理java类,在生产环境中更换类的实现时不需要重新部署,修改文件即可
2. 减少jvm内存占用 spring默认使用单例的模式创建bean,减少内存的占用
3. 通过依赖注入方式建立组件与组件|对象与对象的依赖关系,使对象之间关系更为清晰,方便进行组件代码的维护和管理
总结:
12. 总结
1.spring框架?
spring 框架 项目管理框架 核心 就是用来管理项目中组件对象的创建 使用 销毁
2.spring框架第一个环境搭建
a).引入依赖
spring-core
spring-context
spring-beans
spring-expression
spring-jdbc
spring-web
.....
b).引入spring.xml
名字 随便 位置:resources目录下随便
c).通过spring管理组件的创建
interface UserDAO { void save(String name)}
class UserDAOImpl implements UserDAO
spring.xml
<bean clsss="xxx.UserDAOImpl" id="userDAO" />
d).启动工厂
ApplicationContext context = new ClassPathXmlApplicationContext("xxx/spring.xml");
context.getBean("beanid");
3).spring核心思想?
IOC&DI
IOC:inversion of controll 控制反转
就是将手动通过new关键字创建对象的权利交给spring,由工厂创建对象过程,
DI: Dependency Injection 依赖注入
Spring工厂不仅要创建对象还要在创建对象同时维护组件和组件的依赖关系
AOP: 面前切面编程
4).spring中注入
SET方式[重点] 构造方法 自动注入
SET注入:
定义: 使用set方法形式为成员变量赋值过程称之为set注入
语法:
1.需要谁将谁声明为成员变量并提供公开SET方法
2.在spring配置文件中对应组件标签内部使用 property标签完成注入
1.String + 八种基本类型 + 日期类型 使用 value属性进行注入
<property name="name" value="xx">
注意: spring中日期格式 默认为 yyyy/MM/dd HH:mm:ss
2.对象|引用类型
<property name="" ref="beanid">
3.数组类型
array value 引用: ref bean="beanid"
4.list set map
list value 引用: ref
map entry key="" value="" 引用: key-ref="beanid" value-ref="beanid"
5.properties
props prop key="" <prop key="">value</prop>
5).spring工厂细节
1).创建方式 默认使用单例
<bean class="" id="" scope="singleton(service dao)|prototype(struts2action)">
2).工厂原理
反射+构造方法
Class.forName("xxxx").newInstance();
3).工厂生命周期
单例: 工厂启动工厂中单例对象随之创建 工厂正常关闭 工厂中单例对象随之销毁
多例: 每次使用时工厂进行多例对象的创建 spring工厂不负责多例对象的销毁