标签:Spring、ioc、aop、动态代理、spring事务机制
1.Spring概述
- 是什么?
Spring是一个大家族,即大家说的Spring全家桶,可以看成是不同方向的框架,各有所长,其中Spring框架是基础。从历史的角度,spring是2002年为了解决企业开发中项目模块依赖过多、类之间管理不方便而出现的,用于帮助开发人员创建对象,管理对象之间的关系。
- 核心?
Spring是一个框架,对于任何一个框架,我们都需要关注三点:
第一:该框架有什么用途?→Spring框架可以管理模块、管理对象。
第二:该框架怎么使用?→Spring有诸多固定步骤。
第三:该框架的原理和内部实现?→略。
其中,对于Spring框架,有两个核心:
IOC:控制反转
AOP:面向切面编程
2.IOC控制反转
- 是什么?
IOC是一种思想,相较于以前开发人员手动new 生成对象的正转,在IOC思想中,将对象的创建和管理交由Spring这个容器内部实现,开发人员无需关心细节,只需按照指定格式配置即可,告知Spring我们想要实现的功能。
换言之,Spring容器就相当于大锅炉,可以创建、改造、融合以及给对象赋值。
- 有什么作用?
IOC能够实现在不改变源代码的基础上增加功能,减少对代码的改动,实现业务对象之间的解耦。
- 实例举例?
前面学习的Tomcat服务器中声明了servlet,我们并未手动new servlet对应类,这其实也是IOC思想的实现,不过这里是由Tomcat这个容器实现的。
同时,在mybatis的接口类中,我们调用getMapper方法获取了接口实例对象,其实这也是mybatis给我们创建的,因此这里的容器是mybatis。
- 实现技术?
Spring使用DI(依赖注入)实现了IOC的思想,从而达到创建对象、为对象赋值等操作。
值得一提的是,你可能已经猜到,Spring底层采用的反射机制实现上述功能。
3.第一个Spring模板
前面讲到,我们要把对象的创建交给Spring这个容器,因此有如下几个关键:
配置文件(beans.xml)、接口及其实现类、测试程序。
第一步:创建maven项目,引入spring,juint依赖;
第二步:创建接口和它的实现类;
第三步:beans.xml中用<bean/>标签标识对象,告诉spring我要创建这些对象;
第四步:传入配置信息、创建容器、获取对象、调用方法
【关键1】类名必须使用全限定名,一个bean标签对应一个对象;
【关键2】Spring将对象放在Map集合中存储的;
【关键3】ApplicationContext就是容器,当他扫描配置文件时会逐个生成对象[调用对象的无参构造方法],然后通过其getBean方法获取对应的对象,通过getBeanDefinitionCount得到数量。
【关键4】生成的对象可以是自定义的,也可以是java内置的。
4.Spring容器中对象的赋值_DI依赖注入_xml配置方式
首先说明DI就是依赖注入,用于给容器中的对象赋值的,包括简单类型和引用类型,其中在Spring中,将java基本数据类型及其包装类、String视为简单类型,其他类型视为引用类型。
然后di赋值有两个途径,第一个即是在主配置文件中进行赋值,又称为xml配置方式,在bean标签中引入property语法进行赋值;第二个是采用注解的方式,不过该方法必须要在源代码中赋值。
下面就先讲解一下xml注入:
4.1 set注入
第一个:简单类型的set注入
顾名思义,通过源类的setter方法进行赋值,语法如下:
<bean id="stu01" class="com.zhujie.bao01.Student">
<property name="age" value="300"/>
<!-- setAge(300)-->
<property name="name" value="张三"/>
<property name="GG" value="GGGGGGGG"/>
</bean>
<bean id="date" class="java.util.Date">
<property name="year" value="30"/>
</bean>
这里,通过扫描该xml文件,对id为“stu01”的对象进行赋值,可以看到Spring看到了GG的name值,那么会去寻找源类中的setGG方法,然后将该值"GGGGGGGG"传入,修改其值。
【注意】不难发现,这里GG不一定是原类的属性,同时SetGG方法也不一定能修改原类的属性。
【注意2】当然,对于Date类,由于有setyear方法,故也可以修改。
【注意3】一个property对应一个属性。
【注意4】value右侧必须取双引号,这是XML文件的语法!
第二个:引用类型的set注入
<bean id="stu_school" class="com.zhujie.bao02.Student">
<property name="school" ref="school_ref"/>
<property name="name" value="张三"/>
</bean>
<bean id="school_ref" class="com.zhujie.bao02.School">
<property name="address" value="北京"/>
</bean>
不难发现,与简单类型不同的是,由value→ref,其值为另一个对象。
【注意】这里显然要求Student类中确实有School这个属性,否则不能乱赋值;
4.2 构造注入
顾名思义,通过有参构造方法完成赋值,这就是构造注入。
<bean id="stu_school" class="com.zhujie.bao03.Student">
<constructor-arg name="age" value="90"></constructor-arg>
<constructor-arg name="name" value="王大锤"></constructor-arg>
<constructor-arg name="school" ref="school_ref"></constructor-arg>
</bean>
<bean id="school_ref" class="com.zhujie.bao03.School">
<constructor-arg name="address" value="北京"></constructor-arg>
<constructor-arg name="name" value="bd北京大学"></constructor-arg>
</bean>
<bean id="stu_school2" class="com.zhujie.bao03.Student">
<constructor-arg index="0" value="张包" />
<constructor-arg index="1" value="844" />
<constructor-arg index="2" ref="school_ref2" />
</bean>
//默认从0→1→2的位置
<bean id="stu_school3" class="com.zhujie.bao03.Student">
<constructor-arg value="张包" />
<constructor-arg value="844" />
<constructor-arg ref="school_ref3" />
</bean>
【注意1】这里name中的值为对应构造方法的形参变量名;
【注意2】一个constructor-arg标签表示对象的一个属性;
【注意3】constructor-arg有四个属性,分别是name、index、value、ref:
name:构造方法的形参名;index:构造方法的参数位置,0/1/2/3;
value:简单类型赋值;ref:引用类型赋值。
4.3 引用类型的自动注入
前面两种方式都可以实现简单类型和引用类型的赋值,但Spring考虑到大型项目中模块数多,引用类型手动赋值比较繁琐,因此规定引用类型可以自动注入,根据某些规则自动赋值。
4.3.1 byName自动注入
<bean id="stu_school4" class="com.zhujie.bao04.Student" autowire="byName">
<property name="name" value="张三"/>
<property name="school" ref="school_ref"/>
</bean>
<bean id="school" class="com.zhujie.bao04.School">
<constructor-arg value="北33京"></constructor-arg>
<constructor-arg value="北京3大学"></constructor-arg>
</bean>