初始Spring 文档 完整版

初始Spring
1.Spring官网
spring.io
01.
IOC(Inverse of Control)控制反转
02.
AOP(Aspect Oritend Programming)面向切面编程
03.
OOP(Object Oritend Programming)面向对象编程
四大核心
抽象 封装 继承 多态
04.
OOD(Object Oritend Programming)面向对象设计
工程师 架构师
05.
OOA(Object Oritend Analesis) 面向对象分析
2.对象之间的关系(面向对象分析OOA、面向对象设计OOD、面向对象编程OOP)
分析 ----------- 设计 ----------- 编程
是 泛化 继承 extends
能 实现 接口 implements
有 关系 成员变量
用 依赖 方法中局部变量
3.框架和工具类的区别
工具类
对代码的一个简单封装
框架
站在整个软件系统,所有可能设计到的事物、安全、页面、请求调度、底层ORM、日志。等等东西整合的一种手段
*不用了解架构,但可以做出具体实现
4.spring组成模块(从下到上)
01.Test
测试部分
02.Core Container
核心部分
03.AOP/Instrumentatio
AOP
面向切面编程
Instrumentation
获取计算机软件或者硬盘状态数据的技术。类似如探针
4.Data Access/Web
Data Access
数据访问部分
Web
互联网部分
5.Core Container
01.Beans
02.Core
03.Context
04.SpEL

6. IOC和DI区别
IOC
控制反转(Inversion of Control)
理解一
组件对象的控制权从代码本身转义到外部容器(spring容器)
理解二
在xml中控制,侧重于原理(就是xml中配置bean节点)
DI
Dependency Injection(依赖注入)给对象注入属性值
关系
它们是spring核心思想的不同方面的描述。站在不同维度对同一个概念或者事物的解释
理解一
创建对象实例时,为这个对象注入属性值或其他对象实例(域属性),侧重于实现
01.区别
IOC
侧重于原理
xml配置对象,主要控制反转
DI
侧重于实现
对象初始化过程注入属性值
小结
IOC和DI是站在不同维度对同一个事物进行描述

7.域属性
自定义对象类型,作为另外一个对象的属性
8.第一案例
01.引入jar包
context、beans、core、spEl
*引入spring的核心jar包
02.创建实体类
03.创建applicationContext.xml
<bean id="对象引用名称" class="引用类的全类名">
<property name="属性名" value="属性值">
</bean>
*bean中只能配置实现类,不能配置接口
04.测试类
//使用Application对象指向的是上下文(Spring容器)
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取为Object类型,必须要强制类型转换为引用类型
context.getBean("bean节点id属性");
9.AOP(面向切面编程)
01.AOP的目标
让我们可以“专心做事”
02.AOP原理
02.1
将复杂的需求分解出不同方面,将散布在系统中的公共功能集中解决
02.2
采用代理机制组装起来运行,在不改变原程序的基础上对代码段进行增强处理,增加新的功能
03.AOP图解
黄色(Logging):日志
红色(security):事务
绿色(Persistence):权限

10.配置AOP,增强业务
01.创建一个aop包
02.创建一个增强类实现接口中的方法
02.1接口
MethodBeforeAdvice
实现前置增强
AfterReturningAdvice
实现后置增强
02.2在applicationContext中引用强制类型类
<bean id="标识" class="全类名"></bean>
03.在ApplicationContext.xml中配置aop:config节点
11.定义切入点
01.简单说就是连接点的检查条件
<aop:config>
<!--切点-->
<aop:pointcut id="mypoint" expression="execution(* *..service.*.*(..))"></aop:pointcut>
<!--顾问-->
<aop:advisor advice-ref="AdviceBefore" pointcut-ref="mypoint"></aop:advisor>
</aop:config>
*属性
advice-ref
强制类型:前置还是后置
pointcut-ref
锁定规则:什么样的方法被锁定

02.表达式的切入规则举例(expression)
02.1
public * addNewUser(entity.User)
“*”表示匹配所有类型的返回值
02.2
public void *(entity.User)
“*”表示匹配所有方法名
02.3
public void addNewUser(..)
“..”表示匹配所有参数个数的类型
02.4
* com.service.*.*(..)
匹配com.service包下所有类的所有方法
02.5
* com.service..*.*(..)
匹配com.service包及其子包下所有类的所有方法
03.切点表达式
03.1顾问包装通知
execution([modifiers-pattern?]访问修饰符
ref-type-pattern 返回值类型
[declaring-type-pattern?] 全限定性类名
name-pattern(param-pattern) 方法名(参数名) 包名.类型名.方法名
[throws-pattern?] 抛出异常类型)
03.2方法签名(切面表达式)
切入点表达式要匹配的对象就是目标对象的方法名。所以,execution表达式中明显就是方法的签名。
注意:表达式中加[]的部分表示可省略部分
符号 意义
* 0至多个任意字符
.. 用在方法参数中,表示任意多个参数
或用在报名后,表示当前包及其子包路径
+ 用在类名后,表示当前类及其子类
或用在接口后,表示当前接口及其实现类
案例
execution(public * *(..)) 任意公共方法
execution(* set*(..)) 任何一个以“set”开头的方法
12.构造注入
01.实体类中创建构造方法
02.在ApplicationContext.xml中bean节点中使用constructor-arg节点注入
如:
<bean id="Student" class="cn.zw.entity.Student">
<constructor-arg index="0" value="小黑"></constructor-arg>
<constructor-arg index="1" ref="index01"></constructor-arg>
</bean>
*
index
代表的是构造方法的参数下标,从0开始
value
代表的是对应构造参数注入的值
ref
给域属性赋值时使用
13.P命名空间注入
01.使用属性而不是子元素的形式配置bean的属性,从而简化了配置代码
02.步骤
02.1
使用前要现在Spring配置文件中引入p命名空间
xmlns:p="http://www.springframework.org/schema/p"
*也可以使用快捷方式进行导入Alt+Enter
02.2
使用p命名空间注入属性值
<bean id="Student" class="cn.zw.entity.Student" p:name="小黑" ></bean>
*通过bean节点中的属性p:应用类中的属性名赋值,如果是域属性跟上面的方法类似,p:stu-ref=""引用赋值
14.集合属性注入
<bean id="标识" class="引用类的类型全名称">

<!--给数组中注入-->
<property name="集合属性名">
<array>
<value>小黑</value>
<value>小红</value>
<value>小白</value>
</array>
</property>

<!--给List集合中注入-->
<property name="集合属性名">
<list>
<value>小号</value>
<value>中号</value>
<value>大号</value>
</list>
</property>

<!--给Set集合中注入-->
<property name="集合属性名">
<set>
<value>属性值。。</value>
<value>小安</value>
<value>等等</value>
</set>
</property>

<!--给Map集合中注入-->
<property name="集合属性名">
<map>
<entry key="key属性值">
<value>value属性值</value>
</entry>
</map>
</property>

<!--给Properties类型集合中注入-->
<property name="集合属性名">
<props>
<prop key="key属性值">value属性值</prop>
</props>
</property>
</bean>
15.SpringBean单列和多列设置
01.创建单例类
01.1使用IDEA自动创建
创建Java Class时把Kind选择为Singleton就可以了
02.默认Spring中的bean都是单例的。可以通过设置bean中的属性scope值改变
单例:singleton
多例:prototype

16.自动装配
01.通过设置bean节点中的autowire属性
01.1
通过属性类型自动装配
autowire属性设置为byType
实现思路
通过对象中的属性类型与Mapper文件中的bean节点的类型进行匹配
缺点
如果Mapper文件中有多个相同的bean节点类型时会出现编译异常
01.2
通过属性名称自动装配
autowire属性值设置为byName
实现思路
通过对象中的属性名称与Mapper文件中bean节id名称进行匹配
17.注解
01.概念
Annotation,也叫元数据(MetaData)。一种代码级别的说明。它是JDK1.5及以后版本引入的一个特性,与类、接口、枚举是在同一个层次。它可以声明在包、类、字段、方法、局部变量、方法参数等的前面,用来对这些元素进行说明
02.注解的本质
就是有一个@的接口
原型
//元元素,表示注释类型的程序元素的种类
@Target{TYPE,FIELD,HETHOD,PARAMETER,CONSTRUCTOR,LOCAL_VARIABLE}
//保留,通知编译器如何处理
@Retention(RetentionPolicy.SOURCE)
public @interface 注解名称{}
03.使用步骤(基于注解的依赖注入)
01.在ApplicationContext文件中导入命名空间
01.1
xmlns:context="http://www.springframework.org/schema/context"
01.2在xsi:schemaLocation下添加
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
01.3 注意
也可以使用快捷方式进行导入Alt+Enter
01.4 在beans节点中添加(添加扫描器)
<context:component-scan base-package="cn.zw.entity"></context:component-scan>
*base-package指定的是使用注解的类包名
02.在实体类中
02.1
类上方
@Component 不按照上面三个注解分类,就用此注解
@Repository 持久层
@Service 业务逻辑层
@Controller 控制器
如:@Component("use")
use表示bean节点的id
*如注解中没有定义值,默认是类的小写
属性注入值
@Value("")
04.域属性注入值
04.1
使用jdk提供的注解
@Resource(name = "")
name指定的是bean节点的id
04.2
使用spring提供的注解
@Autowired //表示自动连接
@Qualifier(value = "")
value指定的是bean节点的id
04.3小结
01.
@Resource默认安装byName的方式进行装配。byName的含义:拥有该属性字段名称必须和Spring容器中现有bean的id相同。@Resource比较只能,当根据byName方法装配失败后,它会继续尝试使用byType的方式进行装配,即使类型相同也可以完成装配。
02.
@Autowired默认安装byType的方式进行装配,拥有该注解的字段类型必须和Spring容器中现有类型相同。如果发现与字段想用的bean会导致异常。
03.
@Qualifier将此注解跟@Autowired混合使用时,含义是强制使用byName的方式进行装配,不匹配直接导致异常

06.javax包属于jdk
18.静态代理
在原有的方法上进行方法增强
01.1
缺点:硬盘中会创建真正的物理类
01.2
主题
抽象主题(接口) 真实主题(类) 代理主题(类)
关系
抽象主题中定义方法,真实主题和代理主题都实现抽象主题并实现当中的方法。真实主题负责具体实现,代理主题对象引用真实主题对象的实例后封装并对真实进行增强。
测试类中抽象主题对象实例化真实主题对象,并放入代理主题对象的封装中。后调用代理对象的方法,进行方法增强
简化‘’
抽象主题
赋值定义方法
真实主题
实现抽象主题中方法
代理主题
用于增强真实主题中的方法
19.动态代理
19.1
JDK动态代理
要被代理的对象必须有接口
01.使用步骤(示例)
final IStudent iStudentimpl = new IStudentimpl();
IStudent iStudent = (IStudent) Proxy.newProxyInstance(iStudentimpl.getClass().getClassLoader(), iStudentimpl.getClass().getInterfaces(), new InvocationHandler() {
/*
* proxy:代理对象
* method:目标类型的方法(方法的类型)
* args:方法参数(目标方法的参数)
* */
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("增强中。。。。。。。");// 写增强的方法
Object invoke = method.invoke(iStudentimpl,args);//相当于执行目标类型的方法
return invoke;
}
});
iStudent.doShow();
02.注意
Proxy类和InvocationHandler接口进行导包是要使用java.lang下的包
19.2
CGLIB动态代理(回调类型)
01.
Cglib 底层,注入,编译器已经注入了
本质
在内存中生成被代理类(目标类)的子类
特点
可以在没有接口的情况下代理
对于不使用接口的业务类,无法使用JDK动态代理,cglib采用非常底层的字节码技术,可以为一个类创建子类。
02.示例
final cglibDay cglib = new cglibDay();
//CGLIB动态代理
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(cglib.getClass());
//调度回调函数
enhancer.setCallback(new MethodInterceptor() {
/*
* o:代理对象
* method:目标类型的方法
* objects:目标方法参数
* methodProxy:代理类的方法
* */
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("回调成功");
Object invoke = methodProxy.invoke(cglib, objects);
return invoke;
}
});
cglibDay cglibDay = (cglibDay) enhancer.create();
cglibDay.Show();
20.回调函数
一个方法执行完成后再执行某一段代码的方法
21.经典AOP
01.代理工厂Bean
前置增强 MethodBeforeAdvice 方法执行之前执行
后置增强 AfterReturningAdvice 方法执行之后执行
环绕增强 MethodInterceptor 方法执行前后都有执行
异常增强 ThrowsAdvice 方法执行中出现异常就捕捉
02.使用bean代理工厂实现前置增强
<!--目标类型-->
<bean id="id1" class="cn.Enhance.zw.IStudentImpl"></bean>

<!--增强 通知-->
<bean id="id2" class="cn.Enhance.zw.people"></bean>

<!--代理工厂bean-->
<bean id="zq" class="org.springframework.aop.framework.ProxyFactoryBean">
<!--目标类型-->
<property name="target" ref="id1"></property>
<!--增强-->
<property name="interceptorNames" value="id2"></property>
</bean>
03.使用bean代理工厂实现后置增强
Mapper文件的配置跟上面一样,在增强类中需要实现相应的接口
04.使用bean代理工厂实现环绕增强
Mapper文件的配置跟上面一样,在增强类中的方法实现
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("前置增强中。。。");
methodInvocation.proceed();
System.out.println("后置增强中。。。。");
return null;
}
*需要在前后增强之间调度MethodInvocation对象的proceed方法,用于调度目标对象中的方法
05.使用bean代理工厂实现异常增强
Mapper文件的配置跟上面一样,在增强类中的方法实现
public void afterThrowing(Exception ex){
System.out.println("空指针异常!!!");
}
*需要写接口中注释里的方法,方法名需要和注释中定义的一致
22.顾问(Advisor)
01.
通知Advice是Spring提供的一种切面(Aspect)。但其功能过于简单,只能将切面织入到目标类的所有目标方法中,无法完成将切面织入到指定目标方法中。
顾问Advisor是Spring提供的另一种切面。其可以完成更为复杂的切面织入功能,能选择性的增强切面中的部分方法。
PointcutAdvisor是顾问的一种,可以指定具体的切点。顾问将通知进行包装,会根据不同的通知类型,在不同的时间点,将切面织入到不同的切入点
02.PointcutAdvisor接口中常用实现类
02.1
NameMatchMethodPointcutAdvisor
名称匹配方法切入点顾问
02.2
RegexpMethodPointcutAdvisor
正则表达式方法切入点顾问
03.实例(名称匹配切入点顾问)
在ApplicationContext文件中定义顾问包装通知
01.示例
<!--顾问-->
<bean id="Iadviser" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<!--增强-->
<property name="advice" ref="Enhance"></property>
<!--顾问-->
<property name="mappedNames" value="Show1,Show2"></property>
</bean>
*顾问中的value可以是N个方法名,也可以使用通配符
*id赋值给代理工厂中的interceptorNames属性值中
04.实例(正则表达式方法切入点顾问)
在在ApplicationContext文件中定义顾问包装通知
<!--顾问-->
<bean id="Iadviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增强-->
<property name="advice" ref="Enhance"></property>
<!--顾问-->
<property name="pattern" value=".*Show.*"></property>
</bean>
*顾问中的value填写正则表达式,锁定的方法为方法的全路径
*id赋值给代理工厂中的interceptorNames属性值中
23.顾问和通知的区别
顾问可以选择性的增强,而通知是直接把所有方法都增强
24.正则表达式
用于匹配
运算符 名称 意义
. 点号 表示任意单个字符

+ 加号 表示前一个字符出现一次或者多次

* 型号 表示前一个字符出现0次或者多次
25.自动代理实现
01.Advisor
01.1正则自动代理生成器
DefaultAdvisorAutoProxyCreator
注意:切面只是顾问,对所有的对象都增强
01.2语法
<!--目标对象-->
<bean id="id1" class="cn.AutomaticAgent.IStudentImpl"></bean>

<!--增强-->
<bean id="enhance" class="cn.AutomaticAgent.Preposition"></bean>

<!--顾问-->
<bean id="adviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增强-->
<property name="advice" ref="enhance"></property>
<!--顾问-->
<property name="patterns" value=".*se.*"></property>
</bean>

<!--自动代理-->
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>

*在测试类中使用getBean时使用目标对象的id进行入参
02.1名称自动代理生成器
BeanNameAutoProxyCreator
*切面只是顾问,对所有对象都增强
02.2语法
<!--目标对象-->
<bean id="id1" class="cn.AutomaticAgent.IStudentImpl"></bean>
<bean id="id2" class="cn.AutomaticAgent.IBookImpl"></bean>

<!--增强-->
<bean id="enhance" class="cn.AutomaticAgent.Preposition"></bean>

<!--顾问-->
<bean id="adviser" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<!--增强-->
<property name="advice" ref="enhance"></property>
<!--顾问-->
<property name="patterns" value=".*se.*"></property>
</bean>

<!--自动代理-->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!--目标类型-->
<property name="beanNames" value="id1,id2"></property>
<!--切点-->
<property name="interceptorNames" value="adviser"></property>
</bean>
*自动代理中beanNames是String类型数组,所以可以对多个目标类型
*可以写入顾问和通知

26.AspectJ
01.概念
01.1
一个面向切面的框架,它扩展了Java语言,定义AOP语法,能够在编译器提供代码的织入
01.2
@AspectJ是AspectJ5新增的功能,使用JDK5.0注解技术和正规的AspectJ切点表达式语言描述语言
01.3
Spring通过集成AspectJ实现了以注解的方式定义增强类,大大减少了配置文件中的工作量

02.注意
使用@AspectJ,首先要保证所用的JDK是5.0及以上的版本。将Spring的asm模块添加到类路径中,以处理@AspectJ中所描述的方法参数名
27.AOP的常见术语
01.
JoinPoint(连接点):所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点。
02.
Pointcut(切入点):所谓切入点是指我们要对哪些JoinPoint进行拦截的定义。
03.
Advice(通知/增强):所谓通知是指拦截到JoinPoint之后所要做的事情就是通知。通知分为前置通知,后置通知,异常通知,最终通知,环绕通知 ,Advice是面向方法的
04.
Introduction(引介/引入):Introduction是一种特殊的Advice,是面向类的,可以在运行期间为类动态地添加一些方法或字段。
05.
Target(目标对象):代理的目标对象
06.
Weaving(织入):将Advice(增强)应用给Target(目标对象),创建Proxy的过程
07.
Proxy(代理对象):将advice织入target,生成代理对象
08.
Aspect(切面):是切入点和通知(增强)的总和
--------------------小结--------------------------
切点
匹配到切点表达式的一批方法
连接点
目标类型中所有方法都是连接点
切面
增强类(切点+增强)
织入
将增强和目标对象进行绑定的过程
代理对象
将增强和目标对象进行绑定后的结果
目标对象
代理的目标对象
增强
拦截到 连接点后(切点)要做的事情就是增强
引介
一种特殊的Advice
*切面和代理对象的区别
代码层面:切面就是代理对象
概念层面:代理对象就是切面
28.切面(Aspect)
增强类(切点+增强)
01.概念
无缝面向切面扩展的框架,横切关注点AspectJ(也就是AOP)的动机是发现那些使用传统的编程方法无法很好处理的问题。考虑一个要在某些应用中实施安全策略的问题。安全性是贯穿于系统所有模块间的问题,每个模块都需要应用安全机制才能保证整个系统的安全性,很明显这里的安全策略的实施问题就是一个横切关注点,使用传统的编程解决此问题非常的困难而且容易产生差错,这就正是AOP发挥作用的时候了。@AspectJ 使用了Java5 的注解, 可以将切面声明为普通的Java类(POJO)。
02.增强类中使用注解
02.1增强类
@Aspect
02.2前置增强
@Before
相当于BeforeAdvice
* 就在方法之前执行.没有办法阻止目标方法执行的.
02.3后置增强
@AfterReturning
相当于AfterReturningAdvice、
* 后置通知,获得方法返回值.
03.4环绕增强
@Around
相当于MethodInterceptor
* 在可以方法之前和之后来执行的,而且可以阻止目标方法的执行
03.5异常增强
@AfterThrowing
相当于ThrowAdvice
@After 最终final通知,不管是否异常,该通知都会执行
03.ApplicationContext文件中配置(案例)
<!--目标类型-->
<bean id="service" class="cn.AnnotationAutomaticAgent.IStudentImpl"></bean>
<!--增强-->
<bean id="enhance" class="cn.AnnotationAutomaticAgent.Preposition"></bean>
<!--自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

*在测试类中使用getBean时使用目标对象的id进行入参
04.环绕增强
public void CShow(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕,前置增强中。。。。");
pjp.proceed();
System.out.println("环绕,后置增强中。。。。");
}
*ProceedingJoinPoint代表目标类型对象
05.异常增强
@AfterThrowing(value = "execution(* *..AnnotationAutomaticAgent.*.insert(..))",throwing = "ex")
*throwing:代表捕获到的异常对象,方法中入参是注解定义的值要和方法入参名称一致
29.PointCut注解
01.@Pointcut
简单说就是在增强类中把注解当中的切点表达式提取出来,方便调度
02.案例
@Pointcut("execution(* *..AnnotationAutomaticAgent.*.select(..))")
public void select(){}
@Pointcut("execution(* *..AnnotationAutomaticAgent.*.delete(..))")
public void delete(){}

@Before("select()||delete()")
public void AShow(){
System.out.println("前置增强成功!!!");
}
*在增强的注解中直接调度方法即可,效果一致
“||”是或者,实现多个方法的增强
30.AspectJ基于XML的AOP实现 (开发常用)
01.AOP配置
<aop:config>
<!--切点-->
<aop:pointcut expression="execution(* *..ISomeService.doFirst(..))" id="doFirstPointcut"/>
<aop:pointcut expression="execution(* *..ISomeService.doSecond(..))" id="doSecondPointcut"/>
<aop:pointcut expression="execution(* *..ISomeService.doThird(..))" id="doThirdPointcut"/>
<aop:aspect ref="myAspect">
<!--增强 通知-->
<aop:before method="before" pointcut-ref="doFirstPointcut"/>
<aop:before method="before(org.aspectj.lang.JoinPoint)" pointcut-ref="doFirstPointcut"/>
<aop:after-returning method="afterReturing" pointcut-ref="doSecondPointcut"/>
<aop:after-returning method="afterReturing(java.lang.String)" pointcut-ref="doSecondPointcut" returning="result"/>
<aop:around method="around" pointcut-ref="doSecondPointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="doThirdPointcut"/>
<aop:after-throwing method="afterThrowing(java.lang.Exception)" pointcut-ref="doThirdPointcut" throwing="ex"/>
<aop:after method="after" pointcut-ref="doThirdPointcut"/>
</aop:aspect>
</aop:config>

02.增强类
public class MyAspect {
// 前置通知
public void before(){
System.out.println("前置通知方法before()");
}
public void before(JoinPoint jp){
System.out.println("前置通知方法before() jp = " + jp);
}

// 后置通知
public void afterReturing(){
System.out.println("后置通知方法");
}
public void afterReturing(String result){
System.out.println("后置通知方法 result = " + result);
}

// 环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕通知方法,目标方法执行之前");
// 执行目标方法
Object result = pjp.proceed();
System.out.println("环绕通知方法,目标方法执行之后");
return ((String)result).toUpperCase();
}

// 异常通知
public void afterThrowing(){
System.out.println("异常通知方法");
}
public void afterThrowing(Exception ex){
System.out.println("异常通知方法 ex = " + ex.getMessage());
}

// 最终通知
public void after(){
System.out.println("最终通知方法");
}
}

31.jdbcTemplate
持久层框架
Date----》DB
01.jdbc
性能高,但是最low,代码最多,控制的力度最细
02.jdbctils
给一个sql,返回一个结果
03.研发jdbcTemplate
03.1需要的jar包
<!--spring JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
<!--mysqlDriver-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.39</version>
</dependency>
03.2开发分层
dao、entity、service
*dao层实现类需要继承JdbcDaoSupport类,实现this.getJdbcTemplate().query()/update()方法
03.3编写配置文件
数据源、jdbcTemplate绑定数据源、dao、service
*测试类直接调度bean(service)节点中的id
04.案例
04.1dao层方法实现类
@Override
public List<classes> Show() {
String sql = "select * from classes";
List<classes> query = this.getJdbcTemplate().query(sql, new RowMapper<classes>() {

/*
* ResultSet 读取器
* i 读取器读取的第几条记录
* */
@Override
public classes mapRow(ResultSet resultSet, int i) throws SQLException {
classes ce = new classes();
ce.setId(resultSet.getInt("id"));
ce.setCname(resultSet.getString("cname"));
return ce;
}
});
return query;
}
04.2配置文件(Spring内置数据源)
<!--数据源-->
<bean id="Driver" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql:///managementlanguage"></property>
<property name="username" value="root"></property>
<property name="password" value=""></property>
</bean>

<!--jdbcTimplate 绑定 数据源-->
<bean id="jdbcTimplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="Driver"></property>
</bean>

<!--dao-->
<bean id="Dao" class="cn.Spring_jdbcTimplate.dao.IClassesImpl">
<property name="jdbcTemplate" ref="jdbcTimplate"></property>
</bean>

<!--service-->
<bean id="service" class="cn.Spring_jdbcTimplate.service.IClassServiceImpl">
<property name="iClasses" ref="Dao"></property>
</bean>
*测试类getBean指定的是service节点id
04.3
配置文件关联properties文件
<context:property-placeholder location="classpath: properties文件"></context:property-placeholder>
*classpath属性指定的就是properties文件
05.四种配置数据源的方式
05.1
Spring内置的数据源
命名空间
DriverManagerDataSource
依赖
<!--spring JDBC-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.0.RELEASE</version>
</dependency>
05.2
dbcp(apache)
命名空间
BasicDataSource
依赖
<!--dbcp-->
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
05.3
C3P0
命名空间
ComboPooledDataSource
依赖
<!--c3p0-->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
05.4
druid(alibaba)
命名空间
DruidDataSource
依赖
<!--druid-->
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.0.29</version>
</dependency>
05.5 小结
Spring内置数据源、dbcp、druid中子节点属性名称一致。
C3P0:
driverClass、jdbcUrl、user、password
32.事务
01.概念
能保证N个执行过程可以全部执行成功或者全部回滚到初始状态的机制就是事务
02.四大特性
02.1
原子性
事务中多个操作不可分割的
02.2
一致性
事务操作完成后的结果,数据一定要处于一致性的状态
02.3.
隔离性
两个事务之间执行结果或者执行过程互补干扰
02.4
持久性
事务操作的结果。永久的持久化到硬盘上
03.事务回滚规则
03.1检查异常
提交
03.2运行时异常
回滚
33.Spring事务管理
01.Spring在企业开发中,能灵活的和其他框架进行整合,Spring职责:进行bean管理、事务控制
01.1
核心接口
PlatformTransactionManager
平台事务管理器,提供各个框架进行事务管理
Commit 进行事务提交
Rollback 进行事务回滚
TransactionStatus 返回值是事务的状态
TransactionDefinition
事务定义(配置)信息(隔离、传播、超时、只读),相当于静态属性
02.非ORM事务管理机制(事务管理器)
DataSourceTransaction,用于JDBC、JDBCTemplate、MyBatis、DataSourceTransactionManager。Hibernate无法使用,因为它有单独的事务管理器HibernateTransactionManager,需要提前引入依赖

02.1语法
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--绑定数据源-->
<property name="dataSource" ref="数据源id"></property>
</bean>
*用处:数据源被事务管理,引用事务的管理器
34.事务控制
01事务代理工厂bean
<!--事务管理代理工厂bean-->
<bean class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" id="stockServiceProxy">
<!--绑定事务管理器-->
<property name="transactionManager" ref="事务管理器"/>
<!--目标对象-->
<property name="target" ref="service节点"/>
<!--事务的属性-->
<property name="transactionAttributes">
<props>
<prop key="执行方法名称">事务隔离级别,事务的传播行为,[事务回滚类型]</prop>
<!--
<prop key="方法名">ISOLATION_DEFAULT,PROPAGATION_REQUIRED</prop>
事务隔离级别
读已经提交、读取未提交、可重复读、串行化
-->
</props>
</property>
</bean>
*测试阶段调取事务代理工厂的id
35.注解事务
01.配置文件中添加
<tx:annotation-driven transaction-manager="事务管理器id"></tx:annotation-driven>
02.service分层实现类的方法上添注解
@Transactional()
//rollbackFor=事务回滚类型.class
03.使用原始service对象id进行调度
36.AspectJ配置事务
01.语法
<!--增强-->
<tx:advice id="idAdvice" transaction-manager="事务管理器id">
<tx:attributes>
<!--隔离级别--> <!--传播行为-->
<tx:method name="方法名" isolation="DEFAULT" propagation="REQUIRED" rollback-for="事务回滚类型"/>
</tx:attributes>
</tx:advice>
<!--AOP节点-->
<aop:config>
<!--切点-->
<aop:pointcut id="mypointcut" expression="execution(* *..integrationSSM.service.*.*(..))"></aop:pointcut>
[<!--切面-->]
<!--顾问-->
<aop:advisor advice-ref="idAdvice" pointcut-ref="mypointcut" ></aop:advisor>
</aop:config>
37.事务的隔离级别、传播行为
01.隔离级别
原子性 (atomicity):强调事务的不可分割.
一致性 (consistency):事务的执行的前后数据的完整性保持一致.
隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
持久性(durability) :事务一旦结束,数据就持久到数据库
02.传播行为
01.1.PROPAGATION_REQUIRED
支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
01.2.PROPAGATION_SUPPORTS
支持当前事务,如果当前没有事务,就以非事务方式执行。
01.3.PROPAGATION_MANDATORY
支持当前事务,如果当前没有事务,就抛出异常。
01.4.PROPAGATION_REQUIRES_NEW
新建事务,如果当前存在事务,把当前事务挂起。
01.5.PROPAGATION_NOT_SUPPORTED
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
01.6.PROPAGATION_NEVER
以非事务方式执行,如果当前存在事务,则抛出异常。
01.7.PROPAGATION_NESTED
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

SSM整合

1.整合
整合不是简单的两个框架jar包的堆砌。而是将其中一个框架的一部分工作交给另外一个框架进行维护。
2.框架之间的职责
01.Spring
各种bean的管理和事务控制
02.Spring MVC
负责请求的派发和调度
03.MyBatis
持久层(DB进行交互)用高级接口封装低级操作
3.框架的依赖
01.Spring
spring-core、spring-beans、spring-spel、spring-context、spring-jdbc、spring-tx
02.MyBatis
mybatis-core
4.DAO实现类的命名规则
01.如果接口命名规范是IXXXDAO,内存中构造的接口实现类的名称就是它本身
02.如果接口命名规范是XXXDAO,那么内存中架构的接口实现类的名称为xXXDAO
5.Application和ServletContext
01.application是九大内置对象当中,生命周期最长的一个对象,因为它从程序启动,一直到程序消亡。都可以被访问到。那么application只是Web容器(eg.Tomcat)中的一个实例
02.ServletContext正是application这个对象的类型。虽然ServletContext里面的内容在任何地方都可以访问。我们为什么不将初始化Spring容器这件事也放到ServletContext中。Spring容器是什么?就是一个对象Application
6.思路
我只要能在tomcat启动的某个时机,去注册一个监听器,监听器中可以将Spring初始化,并且放入ServletContext中。以后在任何一个Servlet中。我们都可以共享一个Spring容器。问题就转化成了如何通过代码获取到该Spring容器,我们可以使用一个工具类
WebApplicationContext wac =WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());

7.Spring整合JavaWeb(Servlet)
借助Tomcat来运行web应用
ServletContext到底是什么?
解析:在jsp中,他就是内置对象application的类型,在servlet中就是Servlet上下文
01.对于Web应用来说,ServletContext对象是唯一的,一个Web应用,只有一个ServletContext对象。该对象是在Web应用装载时初始化的,即在Web应用装载时自动执行接口ServletContext的初始化方法。

02.该初始化方法在整个应用中只会执行一次。若将Spring容器的创建语句放到ServletContext的初始化方法中执行,并将创建好的Spring容器作为ServletContext的属性放入其中。以后再需要Spring容器,直接读取该属性值即可。

03.ServletContext对象生命周期与Web应用的相同。即放在其中的属性为全局属性。所以,放入ServletContext中的Spring容器,在整个应用的生命周期中均可被访问。这样就可以保证Spring容器在Web应用中的唯一性了。

04.上述的这些工作,已经被封装在Spring的jar包相关的API中spring-web-4.2.0.RELEASE.jar
8.语法
<!--数据源-->
<bean id="DataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${jdbc.driver}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>

<!--绑定properties文件-->
<context:property-placeholder location="classpath:jdbc2.properties"></context:property-placeholder>

<!--SqlSessionFactory-->
<bean class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="数据源"></property>
<property name="configLocation" value="classpath:MyBatis大配置文件"></property>
</bean> <!--MyBatis大配置文件中只有别名配置-->

<!--Dao-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="dao层路径"></property>
</bean>

<!--Service层注入dao实现-->
<bean id="bookservice" class="cn.BooksSSMIntegration.service.IBookDAOServiceImpl">
<property name="iBookDAO" ref="实现类"></property>
</bean>
<!--*添加Dao层实现类时报红,不用管。跟接口名一致即可-->
<!--事务管理器-->
<bean id="TransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="数据源"></property>
</bean>

<!--注解事务-->
<tx:annotation-driven transaction-manager="TransactionManager"></tx:annotation-driven>
9.包装整个应用中Spring容器的唯一(语法)
01.web.xml文件中
<!--context-param-->
<context-param>
<!--上下文监听器类型的父类属性,Spring配置文件的路径-->
<param-name>contextConfigLocation</param-name>
<!--spring配置文件-->
<param-value>classpath:BooksSSMIntegration.xml</param-value>
</context-param>
*应用程序的整个Servlet对象

<!--监听器-->
<listener>
<!--引用:上下文初始化监听器类-->
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

02.测试类
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext(this.getServletContext());
*直接获取Spring容器实例

猜你喜欢

转载自www.cnblogs.com/SFHa/p/10253630.html