IOC(控制翻转)
概念
把对象的创建、初始化、销毁等工作交给spring容器来做
helloWorld案例
环境
步骤
1、 写一个HelloWorld类
2、 写一个配置文件
3、 客户端
4、 说明:
Spring容器的作用就是为HelloWorld这个类创建对象
Spring容器的结构
创建对象
构造函数(用的最多)
在配置文件中进入如下的配置:
在客户端
HelloWorld类本身:
在控制台打印出了”create object”
可以看出:spring内部默认是调用了HelloWorld这个类的默认的构造函数创建对象
静态工厂
实例工厂
说明:
给工厂类创建了一个对象helloWorldFactory,再利用工厂对象调用工厂方法。
别名
对象的创建时机
案例
执行步骤为1,3,2
以上两种情况是默认值,当spring容器启动的时候创建对象
在bean有这样一个属性
Default 相当于false 在spring容器启动的时候,创建对象
True 在context.getBean时创建对象
False 在spring容器启动的时候创建对象
意义
如果把lazy-init设置为true,则当spring容器启动的时候,检测不到任何,这样会存在很大的安全性隐患,所以一般情况下应该设置lazy-init为default/false。但是如果一个bean中有一个属性,该属性含有大量的数据,这个时候不希望该bean过早的停留在内存中。
这个时候需要用到lazy-init为true。
对象的scope
默认情况(scope=singleton)
在默认情况下放入到spring中的bean是单例的
将来service层和dao层所有的类将放入到spring容器中,所以默认情况下这两个层的类的实例都是单例的,所以不能把数据声明到属性中。如果声明在属性中,将会成为共享的。
Scope为prototype则为多例
创建时机和scope的结合
Scope为prototype,lazy-init为true
在context.getBean时创建对象
Scopse为prototype,lazy-init为false
在context.getBean时创建对象,lazy-init为false失效
当scpose为prototype时,始终在context.getBean时创建对象
Scopse为singleton
是默认情况
Init和destroy
说明:
1、 init方法是由spring内部执行的
2、 只有当spring容器关闭以后才能执行destroy方法,spring容器一般情况下是不会关闭的。只有当web容器销毁掉的时候才可能关闭掉,所以只要一个对象在spring容器中,在spring容器关闭之前,会一直保留。
3、 如果一个bean的配置是scope为”prototype”,则spring容器不负责销毁。
Spring容器做的事情
总结
创建对象
1、 对象的创建方式
2、 对象的创建时机
3、 对象的创建的模式
4、 Init和destroy
5、 创建时机和创建模式的结合
初始化和销毁
DI(依赖注入)
概念
给属性赋值
给pid和name赋值的过程就是di
各种数据类型的编写格式:
Xml
Setter方法
说明:
1、 spring容器实例化person和student两个对象
2、 利用java的反射机制调用属性的setter方法赋值
3、 在客户端利用context.getBean方法把spring容器中的一个对象获取了。
-----------------------
说明:
1、 启动spring容器
2、 实例化person对象和student对象
3、 给person中的属性赋值
4、 调用person的init方法初始化
5、 客户端利用context.getBean获取对象
-----------------------------------
说明:
1、 启动spring容器
2、 实例化person对象
3、 因为person对象依赖于student对象,所以在实例化person对象的时候必须实例化student对象,所以这个时候,在student对象上的lazy-init为true将失效。
-----------------------------------------
说明:
1、 启动spring容器
2、 实例化student
3、 在客户端执行context.getBean方法获取person对象
4、 实例化person对象,调用person的构造函数
5、 调用person中的setStudent方法,给person中的student赋值
6、 执行person中的init方法
7、 Person对象调用方法
------------------------------------------------
构造器
说明:
1、 constructor-arg代表指定的构造器函数的其中的一个参数
2、 可以利用index,ref,value,type来指定唯一的构造器
3、 如果一个bean的配置中没有constructor-arg属性,则必须利用默认的构造函数创建对象。
4、 所以在写一个javabean的时候,应该提供属性的setter方法,默认的构造器,带参数的构造器
注解
概念
1、 用来解释说明
2、 注解必须作用在类的某一个部分
3、 注解的作用域范围(java,class,jvm)
4、 注解解析器
自定义的注解
注解解析器
Spring中的注解
在spring的配置文件中
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
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-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<bean id="helloworld" class="com.wakev.spring.ioc.helloworld.HelloWorld">
</bean>
<!--
把person和student放入到spring容器中
-->
<bean id="person" class="com.wakev.spring.di.annotation.Person"></bean>
<bean id="student" class="com.wakev.spring.di.annotation.Student"></bean>
<!--
启动依赖注入的注解解析器
-->
<context:annotation-config></context:annotation-config>
</beans>
说明:
1、 启动spring容器
2、 spring容器内部创建了两个对象person和student
3、 当spring容器解析到
<context:annotation-config></context:annotation-config>
启动依赖注入的注解解析器:
4、 spring容器在容器中查找所有的bean(prerson,student)
5、 看哪些bean的属性上面是否有Resource注解
6、 如果属性上面有该注解,再次检查是否有name属性
7、 如果没有name属性,则会把该注解标注的属性的名称获取到和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则按照类型进行匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。
8、 如果有name属性,则把name属性的值解析出来和spring容器中的id做匹配,如果匹配成功,则赋值,如果匹配不成功,则报错。
9、 从上述的步骤可以看出注解的效率比较低,xml的效率比较高,注解书写比较简单,xml书写比较复杂。
Spring容器的关于di的注解
按照类型匹配
按照ID匹配
注解只能应用与引用类型
IOC和DI的意义
案例1
需求
编写一个文档管理系统,在该系统中有如下的结构:
1、 Document:interface
readDocument
writeDocument
2、 WordDocument 是Document的实现类
readDocument
writeDocument
3、 ExcelDocument
readDocument
writerDocument
4、 PDFDocument
readDocument
writeDocument
5、 DocumentManager
Document document;
readDocument()
writeDocument()
做法1
说明:
上述的代码是不完全的面向接口编程
做法2
说明:
在代码端没有出现具体的类,完全的面向接口编程。
在spring容器的配置文件中决定了documentManager中的接口的实现类是什么。而这个过程和java代码端没有关系。
案例2
需求
把action调用service,service调用dao用spring来完成
实现
意义
实现了完全的面向接口编程,在代码端没有要关系一个接口的实现类是什么。