最是人间留不住,朱颜辞镜花辞树。这篇文章主要讲述#私藏项目实操分享#Spring IOC案例相关的知识,希望能为你提供帮助。
一、Spring IOC(DI) - 控制反转(依赖注入)概述:
所谓的控制反转,就是将对象的创建及生命周期管理的过程交给Spring来处理的过程,被称之为控制反转。从此在开发当中不在需要去关注对象的创建以及对于对象生命周期的管理,而是在需要的时候都由Spring框架来提供。由spring框架创建对象及管理其生命周期的机制被称为--控制反转。
在创建对象的过程当中,spring可以依据配置文件对这个对象的属性进行设置,这个过程就是--依赖注入(DI)。
二、Spring ioc入门案例
1、下载spring相关jar包
2、解压下载好的压缩包(一包都是解压即用)
3、创建一个java项目,报相关的jar文件导入
4、加入到工程-->
add
to build path
5、通过xml文件使用spring框架
--在src下创建一个spring配置文件,名字任意,但是通常情况下,都会使用applicationContext.xml(一般情况下,都会将配置文件放到src目录下)
6、通过配置文件生成<
bean>
标签创建对象,交由spring框架管理
<
bean id="" class="">
id--就是这个类的标识,可以通过这个id找到相对应的class对象
class--通过class给定的字符串,然后通过反射机制去加载这个类
代码演示:
Person类:
publicclass Person
publicvoid say()
System.out.println("hellospring~");
test类:
@Test
publicvoid test01()
//原始的调用对象
//Personp = new Person();
//p.say();
//通过spring容器获取这个对象
ApplicationContextcontext = new
ClassPathXmlApplicationContext("applicationContext.xml");
Personp = (Person) context.getBean("person");
p.say();
三、IOC实现原理:
在初始化一个Spring容器时,Spring会去解析指定的xml文件,当解析到其中的< bean> 标签时,会根据该标签中的class属性指定的类的全路径名,通过反射创建该类的对象,并将该对象存入内置的Map中管理。其中键就是该标签的id值,值就是该对象。之后,当通过getBean方法来从容器中获取对象时,其实就是根据传入的条件在内置的Map中寻找是否有匹配的键值,如果有则将该键值对中保存的对象返回,如果没有匹配到则抛出异常。
默认情况下,多次获取同一个id的bean,得到的将是同个对象。
即使是同一个类,如果配置过多个< bean> 标签具有不同的id,每个id都会在内置Map中有
一个键值对,其中的值是这个类创建的不同的对象同一个< beans> 标签下不允许配置多个同id的< bean> 标签,如果配置则启动抛异常
四、IOC获取对象的方式:
1)通过context.getBean()方式获取
a.用id获取
b.用class获取
通过class方式获取bean时,如果同一个类配置过多个bean,则在获取时因为无法确定到底要获 取哪个bean会抛出异常。
而id是唯一的,不存在这样的问题,所以建议大家尽量使用id获取bean。
< ?xmlversion="1.0" encoding="UTF-8"?> < beansxmlns="http://www.springframework.org/schema/beans" 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-3.2.xsd??"> < bean id="person"class="com.biem.beans.Person"> < /bean> < /beans> public classPerson publicvoid say() System.out.println("hellospring~"); |
五、别名标签
在Spring中提供了别名标签< alias> 可以为配置的< bean> 起一个别名,要注意的是这仅 仅是对指 定的< bean> 起的一个额外的名字,并不会额外的创建对象存入map。
< alias name="要起别名的bean的id"alias="要指定的别名"/>
< bean id="person"class="com.biem.beans.Person"> < /bean> < alias name="person"alias="p1"/> |
六、spring创建对象的方式:
a.通过类的无参构造器创建:
当用最普通方式配置一个< bean> 时,默认就是采用类的无参构造创建对象。在Spring容器初始化时,通过< bean> 上配置的class属性反射得到字节码对象,通过newInstance()创建对象
Class c = Class.forName("类的全路径名称") |
Object obj = c.newInstance() |
这种方式下spring创建对象,要求类必须有无参的构造,否则无法通过反射创建对象,会抛
出异常。
public classPerson
//这种方式没有无参构造器,使用spring框架创建对象会报错
publicPerson(String age)
publicvoid say(String age)
System.out.println("hellospring~");
b.通过静态工厂创建对象
很多的时候,我们面对的类是无法通过无参构造去创建的,例如该类没有无参构造、是一抽
象类 等等情况,此时无法要求spring通过无参构造创建对象,此时可以使用静态工厂 方式创建对象。
public classCalendarStaticFactory
publicstatic Calendar getCalendar()
returnCalendar.getInstance();
< bean id="calendar"
class="com.biem.factory.CalendarStaticFactory"
factory-method="getCalendar"> < /bean>
/**
* spring创建对象的方式:通过静态工厂创建
*/
@Test
publicvoid test02()
ApplicationContextcontext = new
ClassPathXmlApplicationContext("applicationContext.xml");
Calendarc1 =(Calendar)
context.getBean("calendar");
Calendarc2 =(Calendar)
context.getBean("calendar");
System.out.println(c1==c2);
c.通过实例工厂创建对象
实例工厂也可以解决类中没有无参构造无法创建对象的问题,解决方法跟静态工厂类似。只不过实例工厂提供的方法不是静态的。spring需要先创建出实例工厂的对象,在调用实例工厂对象上指定的普通方法来创建对象。所以实例工厂也需要配置到Spring中管理。
public classCalendarFactory publicCalendar getCalendar() returnCalendar.getInstance(); |
< beanid="calendarFactory"class="com.biem.factory.CalendarFactory"> < /bean> < bean id="calendar"factory-bean="calendarFactory"factory-method="getCalendar"> < /bean> |
/** * spring创建对象的方式:通过实例工厂创建 */ @Test publicvoid test03() ApplicationContextcontext = newClassPathXmlApplicationContext("applicationContext.xml"); Calendarc = (Calendar)context.getBean("calendar"); System.out.println(c); |
d.通过spring工厂创建对象
Spring内置了工厂接口,也可以通过实现这个接口来开发Spring工厂,通过这个工厂创建对象。
public classCalendarSpringFactory implements FactoryBean< Calendar> /** * 工厂生产的对象并返回 */ @Override publicCalendar getObject() throws Exception returnCalendar.getInstance(); /** * 工厂生成对象的类型 */ @Override publicClass< ?> getObjectType() returnCalendar.class; /** * 工厂生成的对象是否是单例 * 如果是true--是单例 * 如果是false--是多例 */ @Override publicboolean isSingleton() returnfalse; |
< beanid="calendar"class="com.biem.factory.CalendarSpringFactory"> < /bean> |
/** * spring创建对象的方式:通过spring工厂创建 */ @Test publicvoid test04() ApplicationContextcontext = newClassPathXmlApplicationContext("applicationContext.xml"); Calendarc1 = (Calendar)context.getBean("calendar"); Calendarc2 = (Calendar)context.getBean("calendar"); System.out.println(c1==c2); |
7、单例和多例
spring容器管理的bean在默认情况下,是单例的,也就是说,一个bean只创建一个对象,然后存到map当中,之后无论获取多少次该bean,都是同一个对象。
spring默认采用的单例方式,减少了对象的创建,减少了内存的消耗。
但是在实际的开发当中有存在多例需求的情况,spring提供了选项,可以将这个bean设置为多例方式。
< !-- scope属性:控制当前bean创建的模式 singleton:当前的bean处在单例模式当中,默认就是此模式 prototype:当前的bean处在多例模式下 --> < bean id="cart"class="com.biem.beans.Cart"scope="prototype"> < /bean> |
bean在单例模式下的生命周期:
bean在单例模式下,spring容器启动时解析xml发现该bean标签后,直接创建该bean的对象
存入内部map中保存,此后无论调用多少次getBean()获取该bean都是从map中获取该对象返
回,一直是一个对象。此对一直被Spring容器持有,直到容器退出时,随着容器的退出对
象被销毁。
bean在多例模式下的生命周期:
bean在多例模式下,spring容器启动时解析xml发现该bean标签后,只是将该bean进行管
理,并不会创建对象,此后每次使用getBean()获取该bean时,spring都会重新创建该对象
返回,每次都是一个新的对象。这个对象spring容器并不会持有,什么销毁取决于使用该对
象的用户自己什么时候销毁该对象。
8、懒加载机制
Spring默认会在容器初始化的过程中,解析xml,并将单例的bean创建并保存到map中,这样的机
制在bean比较少时问题不大,但一旦bean非常多时,spring需要在启动的过程中花费大量的时间
来创建bean花费大量的空间存储bean,但这些bean可能很久都用不上,这种在启动时在时间和
空间上的浪费显得非常的不值得。所以Spring提供了懒加载机制。所谓的懒加载机制就是可以规定指定的bean不在启动时立即创 建,而是在后续一次用到时才创建,从而减轻在启动过程中对时间和内存的消耗。
懒加载机制只对单例bean有作用,对于多例bean设置懒加载没有意义。
方式一:未指定的bean设置懒汉模式
< !--lazy-init : 懒汉模式true--开启懒汉模式--> < bean id="cart"class="com.biem.beans.Cart"lazy-init="true"> < /bean> |
方式二:全局加载懒汉模式
< ?xmlversion="1.0" encoding="UTF-8"?> < beansxmlns="http://www.springframework.org/schema/beans" 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-3.2.xsd??" default-lazy-init="true" > < bean id="cart"class="com.biem.beans.Cart" > < /bean> < /beans> |
9、配置初始化和销毁的方法:
在Spring中如果某个bean在初始化之后 或销毁之前要做一些 额外操作可以为该bean配置初始 化和销毁的方法 ,在这些方法中完成要功能。
public classProductDao publicvoid init() System.out.println("链接数据库。。。"); publicvoid destroy() System.out.println("断开链接。。。"); publicvoid add() System.out.println("添加商品。。。"); publicvoid update() System.out.println("更新商品。。。"); publicvoid del() System.out.println("删除商品。。。"); publicvoid query() System.out.println("查询商品。。。"); |
< ?xmlversion="1.0" encoding="UTF-8"?> < beansxmlns="http://www.springframework.org/schema/beans" 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-3.2.xsd??" default-lazy-init="true" > < bean id="product"class="com.biem.beans.ProductDao" init-method="init"destroy-method="destroy"> < /bean> < /beans> Spring中关键方法的执行顺序: 在Spring创建bean对象时,先创建对象(通过无参构造或工厂),之后立即调用init方法来执 行初始化操作,之后此bean就可以拿来调用其它普通方法,而在对象销毁之前,spring容器 调用其destory方法来执行销毁操作。 |
推荐阅读
- Sql Server快速建表
- jsHelper
- 用SQL语句,删除掉重复项只保留一条
- #yyds干货盘点#深入浅出,一文吃透mysql索引
- #yyds干货盘点#30个类手写Spring核心原理之MVC映射功能
- shell 编程之循环语句echo用法
- ADO.NET 数据连接查询
- 移动的彩虹
- #yyds干货盘点#Hystrix