系统学习Spring之Spring in action(二)
每日一叨:
非常抱歉,由于刚刚接触博客园,很多功能都还没有怎么熟悉,所以第一篇文章的排版不够好,一些重要的信息不够醒目,在接下来的文章里,我会有所改善,
若有哪个地方理解的有问题,可以与我交流,我会即时更正.
文章导读:
1.Factory-Method(指定构造方法)
2.BeanScope(Bean的生命周期)
3.Init-Method与Destory-Method(初始Bean与销毁Bean)
4.通过Bean标签中的<properties></properties>标签注入基本类型和对象类型
知识点:
在上一篇文章中,学习了如何用构造方法去注入对象,当注入对象的时候调用哪一个构造方法是被动的取决与构造参数,若构造参数为空,则调用默认的
构造器,若不为空,则调用构造方法的参数类型与传递过来的参数类型相对应的构造方法.除了这种被动式的通过构造方法来注入对象,是否可以手动指
定一个普通静态方法,使其完成对象的注入呢?
1.Factory-Method(指定构造方法)
在学习指定构造方法之前,我想都应该知道什么是单例吧,为了保险起见,我还是先说一下什么是单例吧.
单例:保证一个类仅有一个实例,并提供一个访问它的全局访问点.
下面即将使用指定构造方法完成一个单例Demo.
首先创建一个Ricky类:
public class Ricky { //懒汉式单例类.在第一次调用的时候实例化 //私有的默认构造方法,也就是无法使用new运算符来创建一个对象 private Ricky() {} //创建一个静态对象.也就是我啦,Name:刘帅 Age:24 private static Ricky single=null; //静态工厂方法 public synchronized static Ricky getInstance() { if (single == null) { single = new Ricky(); } return single; } }
配置Spring的configuration文件:
<bean id="ricky" class="com.ricky.zero.pojo.Ricky" factory-method="getInstance"></bean>
当注入Ricky对象的时候,不在去调用Ricky类的构造方法,而是直接调用指定好的getInstance方法,该方法是一个普通的静态方法.
测试单例模型能否成功
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); Ricky ricky1 = (Ricky)ctx.getBean("ricky"); Ricky ricky2 = (Ricky)ctx.getBean("ricky"); if(ricky1==ricky2){ System.out.println("两个对象是同一个对象"); }else{ System.out.println("两个对象不是同一个对象"); }
运行后若得到:
两个对象是同一个对象,则表明测试成功.
2.BeanScope(Bean的生命周期)
Spring中Bean的生命周期有五种,分别是singleton,prototype,request,session,global-session.最常用的是singleton和prototype.
Spring中Bean的默认生命周期是singleton.
通过这个图,我想比我的叙述要直观的多.还是讲下最常用的两个生命周期,singleton,prototype.
singleton:是Bean的默认生命周期,在每个Spring Container中,只定义了一个实现(俗称单例).
prototype:允许Bean实例化无数次.(每实例第一次,它会new出一个全新的对象)
做一个简单的演示:
首先创建一个狗的对象:
public class Dog{ //狗的名字 private String dogName; //狗的年龄 private int dogAge; //省略getter和setter }
先演示,singleton生命周期,其实我们一直都在使用,以前是隐式定义,这次我们显示的定义bean的生命周期.
<bean id="dog" class="com.ricky.zero.pojo.Dog" scope="singleton"></bean>
测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); Dog dog1 = (Dog)ctx.getBean("dog"); Dog dog2 = (Dog)ctx.getBean("dog"); if(dog1==dog2){ System.out.println("你说的两条狗是同一条狗."); }else{ System.out.println("你说的两条狗不是同一条狗."); }
测试结果:你说的两条狗是同一条狗.
由上可证,当Bean的生命周期是singleton的时候,无论你注入多少个对象,它们都是同一个对象,因为在同一个Spring container中,生命周期为singleton的
对象是单例.
演示prototype:只需要修改Spring configuration配置即可,修改如下:
<bean id="dog" class="com.ricky.zero.pojo.Dog" scope="prototype"></bean>
运行测试:无需修改,直接运行.
测试结果:你说的两条狗不是同一条狗.
通过测试结果,可以看出,当Bean的生命周期是prototype的时候,每当你注入一个对象的时候,它都会重新new一个全新的对象出来.
在Spring Scope到这里就结束了,如果想继续了解下面3种生命周期可以去查阅Spring官方的文档.
3.Init-Method与Destory-Method(初始化Bean与销毁Bean)
Spring container中bean的init-method属性是用于在加载bean之前调用init-method指定的方法,而destory-method是用于在销毁bean之前调用
指定的方法.
演示:
public class Computer { //将会在加载computer Bean之前调用. public void turnOnComputer(){ System.out.println("电脑正在启动,请稍候..."); } //将会在清除computer Bean之前调用 public void turnOffComputer(){ System.out.println("电脑正在关闭中,请稍候..."); } }
修改Spring configuration配置文件,修改如下:
<bean id="computer" class="com.ricky.zero.pojo.Computer" init-method="turnOnComputer" destroy-method="turnOffComputer"></bean>
测试运行:
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
测试结果:
电脑正在启动,请稍候...
由于bean不要在用完后立即清除,导致没能看到destory-method的结果,当bean被清除的时候,它会调用destory-method的.
除了可以指定bean的init-method和destory-method,我们还可以指定,Spring Container的默认init-method和destory-method,
方法如下:直接在<beans>default-init-method="初始方法名" default-destroy-method="销毁方法名"></beans>
4.通过Bean标签中的<properties></properties>标签注入基本类型和对象类型
Spring可以通过configuration配置文件中properties标签中的value值注入到setter属性的参数列表中,value的值既可以是基本类型,
也可以是对象类型.
演示:
创建一个Game接口,方便下面使用.
public interface Game { //获取游戏名称 public void getGameName(); }
创建一个Dota类,继承之Game,类中有两个私有的属性.
一个是String类型,一个是War3类型.
下面将通过Spring Configuration 中properties标签向setter方法中注入,String类型的值和War3类型的值.
public class Dota implements Game { //Dota游戏作者 private String author; //Dota玩家同样会玩War3 private War3 war3; public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public War3 getWar3() { return war3; } public void setWar3(War3 war3) { this.war3 = war3; } @Override public void getGameName() { // TODO Auto-generated method stub System.out.println("大家好,我们名字叫Dota,来自 " + this.author + " 之手"); this.war3.getGameName(); } }
配置Spring Configuration:
<bean id="war3" class="com.ricky.zero.pojo.War3"></bean> <bean id="dota" class="com.ricky.zero.pojo.Dota"> <property name="author" value="冰蛙"></property> <property name="war3" ref="war3"></property> </bean>
首先实例化一个war3对象,在dota这个bean中使用了两个properties标签,其实这个标签的name属性是要注入setter参数列表的参数名,若是基本类型可以
直接通过value属性把值传递到setter参数列表中的参数里.若是对象类型则可以使用ref属性,ref属性的值是bean的ID.对象类型中String除外,String也是
可以直接通过value直接注入的.因为Spring的value类型都是以字符传递值,然后识别解析到对应的类型的参数列表中.
运行测试:
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml"); Dota dota = (Dota)ctx.getBean("dota"); dota.getGameName();
测试结果:
大家好,我们名字叫Dota,来自 冰蛙 之手
大家好,我的名字叫魔兽争霸,相信你们很多人都已经认识我了.
若结果如上,说明通过properties注入普通类型和对象类型成功.
--------------------------------申明----------------------------
本文可以免费阅读以及转载,转载时请注明出处.
本人邮箱:Ricky_LS@163.com
Thank you for your corporation.