Spring Framework创建对象时间、初始化与销毁、IOC与DI结合的真正意义……
恍恍惚惚大二一年又过去了,马上要进入大三了,第一篇博客是刚上大二时候写的,到现在怎么感觉博客质量倒不如从前了,一直忙碌,却感觉没有忙出什么成效来,更博也少了,也只是贴上些代码,文字的描述更少了,感觉自己变得敷衍了,看来是应该反思反思这一年都干了什么。好吧,废话也不多说了,先贴上这篇最近学习spring的一点总结吧
1.什么是Spring,Spring是用来干嘛的?
Spring是一个非常活跃的开源框架;它是一个基于Core来构架多层JavaEE系统的框架,它的主要目地是简化企业开发.
Spring以一种非侵入式的方式来管理你的代码,Spring提倡”最少侵入”,这也就意味着你可以适当的时候安装或卸载Spring
Spring就是一个容器
2.Spring的配置文件
默认情况下是applicationContext.xml文件。可以建立很多xml文件,工程中一般都是这样配置的。
3.Spring创建对象的时间
a.(在默认的情况下,启动Spring容器的时候创建对象)
好处:因为是在Spring容器启动的时候就创建对象,所以只要配置文件书写错误,在一开始的时候(web容器启动)就能发现错误
b.懒加载lazy-init=”true” (在context.getBean时才要创建该对象)
<bean id=”” class=”” lazy-init=”true”></bean>
4.怎么证明Spring容器是单例的还是多例的
a.我们可以写一个小例子,看地址,在Spring容器中的对象默认是单例的,因为对象是单例的,所以只要在类上声明一个属性,该属性中含有数据,那么该属性是全局的(这么做是很危险的),如下图
<bean id="helloWorld" class="com.zkx.spring.scope.HelloWorld"></bean>
测试:
@Test public void testScope_Default(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld"); HelloWorld helloWorld2 = (HelloWorld)context.getBean("helloWorld"); System.out.println(helloWorld); System.out.println(helloWorld2); }
结果 com.zkx.spring.scope.HelloWorld@43763e0b
com.zkx.spring.scope.HelloWorld@43763e0b
证明了Spring容器中的对象默认是单例的
b.如果说scope为”prototype”的时候,spring容器产生的对象就是多实例,无论lazy-init为什么值,都是在context.getBean时才要创建对象
<bean id="helloWorld2" class="com.zkx.spring.scope.HelloWorld"
scope="prototype"></bean>
测试结果是2个不同的地址,这里就不上测试代码了
注:在web开发中,通常把Srvice层和Dao层放进Spring容器中,整成单例的,这样你在浏览器输入一个url,一千次访问,一万次访问,Action调用Service,Service调用Dao,那么也只会产生一个Srvice层的对象和一个Dao层的对象,那么JVM销毁这些对象的压力大大减轻
5.什么是IOC?
IOC:Inversion of Control 控制反转
IOC即Spring的控制反转:把对象的创建、初始化、销毁等工作交给spring容器来做。由spring容器控制对象的生命周期。
6.Spring的初始化和销毁
在applicationContext.xml文件中,加上下面的代码
<bean id="helloWorld" class="com.zkx.spring.initdestroy.HelloWorld"
init-method="init"
destroy-method="destroy"></bean>
初始化方:init-method
销毁方法 :destroy-method
public class HelloWorld { public HelloWorld(){ System.out.println("aaaa"); } public void hello(){ System.out.println("hello world"); } public void init(){ System.out.println("init"); } public void destroy(){ System.out.println("destroy"); } }
@Test public void testInitDestroy(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld helloWorld = (HelloWorld)context.getBean("helloWorld"); helloWorld.hello(); ClassPathXmlApplicationContext applicationContext = (ClassPathXmlApplicationContext) context; applicationContext.close();//spring容器关闭 }
测试结果:
aaa
Init
Helloworld
destory
Spring容器关闭时,调用销毁方法,如果spring容器没有执行close方法,则不执行销毁方法,如果spring容器执行了close方法,在执行该方法之前要执行销毁方法;在构造方法之后,立刻执行init方法(destroy用途不是很大,init方法用途很多)
7.Spring的执行流程
8.DI?
DI:Dependency Injection 依赖注入
依赖注入简单的说就是给属性赋值,有2种注入的方法:
a.使用构造器注入
使用xml的注入方式
通过参数的顺序
<constructor-arg index="0"> <value>张三</value> </constructor-arg> <constructor-arg index="1"> <value>56</value> </constructor-arg>
通过参数的类型
<constructor-arg type="java.lang.Integer"> <value>56</value> </constructor-arg> <constructor-arg type="java.lang.String"> <value>张三</value> </constructor-arg>
b.使用属性set方法进行注入
使用xml的注入方式:
简单Bean的注入
简单Bean包括两种类型:包装类型和String
<bean id="personService" class="com.zkx.bean.impl.PersonServiceImpl"> <!-- 基本类型,string类型 --> <property name="age" value="20"></property> <property name="name" value="张无忌"></property> </bean> <!-- 引用其他Bean --> <bean id="person" class="com.zkx.bean.Person" /> <bean id="personService" class="com.zkx.bean.impl.PersonServiceImpl"> <property name="person" ref="person" /> </bean>
9.IOC和DI结合的真正意义
a.不完全的面向接口编程(客户端还得关心这个接口是由哪个类实现的)
如下图就是不完全的面向接口编程(WordDoment等类实现了Document接口,具体类的实现我就不列出来了),包括我以前那篇关于面向接口编程的博客,也是不完全的面向接口编程
@Test public void testDocument_NOSpring(){ //为不完全的面向接口编程 Document document = new WordDocument(); DocumentManager documentManager = new DocumentManager(); documentManager.setDocument(document); documentManager.readDocument(); documentManager.writeDocument(); }
b把documentManager,wordDocument,excelDocument,pdfDocument放入到spring容器中
<bean id="documentManager" class="com.zkx.spring.iocdi.document.DocumentManager"> <property name="document"> <ref bean="wordDocument"/> </property> </bean> <bean id="wordDocument" class="com.zkx.spring.iocdi.document.WordDocument"></bean> <bean id="excelDocument" class="com.zkx.spring.iocdi.document.ExcelDocument"></bean> <bean id="pdfDocument" class="com.zkx.spring.iocdi.document.PDFDocument"></bean>
Java代码端的测试
@Test public void testDocument_Spring(){ ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); DocumentManager documentManager = (DocumentManager)context.getBean("documentManager"); documentManager.writeDocument(); documentManager.readDocument(); }
没有出现一个WordDocment等,也就是说java代码这头,只需要完全面向接口编程就行了,只需要关心Docment的API实现什么样的功能,至于说这个Docment具体是谁,我不关心
这就是IOC和DI结合的真正意义:
Java代码端完全的面向接口编程(现在很多容器都有这功能,都是模仿Spring的)