一、今日目标
1.Spring AOP的概念以及介绍
2.Spring AOP的应用(基于aspectij的xml版)
3.Spring AOP的应用(基于注解版)
4.Spring的事务管理
一. Spring AOP的概念以及介绍
- 概念:
AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现
程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重
要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各
部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。
AOP实际是GoF设计模式的延续,设计模式孜孜不倦追求的是调用者和被调用者之间的解耦,提高代码的灵活性
和可扩展性,AOP可以说也是这种目标的一种实现。 - Aop功能:
Aop的功能主要是为了拦截或者实现日志安全检查,一些检查的工作,aop也常用于事务管理,防止垃圾数据进
入数据库。 - 横向切割和纵向切割:
- Aop采用的横向切割技术,在不修改源代码的情况下完成添加功能的技术;
- 纵向切割技术,修改源代码情况下完成功能的操作
4.Aop里有五种增强的方式:
增强/通知其实一个要添加的逻辑业务处理的方法,五种实现横向切割技术的方式 - 前置增强,表示在目标方法执行前实施增强
- 后置增强,表示在目标方法执行后实施增强
- 引介增强,表示在目标类中添加一些新的方法和属性。(了解)
- 环绕增强,表示在目标方法执行前后实施增强
- 异常增强,表示在目标方法抛出异常后实施增强。
- 最终增强,表示在目标方法执行后不管有没有异常抛出总是实施增强
二. Spring AOP的应用 - 准备工作
加入依赖坐标
Aspectij这个jar包,不是spring框架的一部分,可以作为spring框架的一个组件,用来配合aop完成相应的操作
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
</dependency>
<!-- spring的四个核心组件:context core beans web -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--spring的测试工具类-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--spring对aop模块的支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--spring自己也可以操作数据库-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--spring的事务管理-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>4.3.18.RELEASE</version>
</dependency>
<!--mysql-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.38</version>
</dependency>
<!-- c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>
创建核心配置文件并且加入相应的约束
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
- 基于aspectJ的xml版
- 创建一个目标类
/* 目标类,就是在操作过程中手动调用的类
*/
public class TargetClass {
public void login(){
System.out.println("目标类方法:登录成功");
}
}
- 创建一个增强类
/*
* 增强类,在调用目标类的时候spring利用aop思想,执行预编译的类
*/
public class HandleClass {
public void check(){
System.out.println("登录校验检查");
}
}
- 修改核心配置文件,加入bean管理和aop配置
前置增强
<!-- 对目标类进行bean注册 -->
<bean id="targetClass" class="cn.kgc.xml.TargetClass"></bean>
<!-- 对增强类进行bean注册 -->
<bean id="handleClass" class="cn.kgc.xml.HandleClass"></bean>
<!-- aop编程思想 -->
<aop:config>
<!-- 切点 对应的是目标类的方法,在aop配置中可以有多个aop:ponitcut
expression称之为表达式,属性值等于execution(* cn.kgc.xml.TargetClass.login(..))
execution表示执行,该方法中三个参数,参数1表示* ,参数2是一个空格,参数3表示目标类方法的地址
参数3方法中一定要携带两个点作为参数,第一个点表示参数类型,第二点表示参数名称,
注意:不管你的方法中是否有参数,都必须有两个点
id属性表示切点名称
-->
<aop:pointcut expression="execution(* com.kgc.xml.TargetClass.login(..))" id="mycut1"/>
<!-- 切面 对应的是增强类的方法 ref映射增强类的bean注册id -->
<aop:aspect ref="handleClass">
<!-- 前置增强
method属性表示方法的意思,对应的是增强类的中具体的方法名称
pointcut-ref表示当前切面中的方法所对应的切点
-->
<aop:before method="check" pointcut-ref="mycut1"/>
</aop:aspect>
</aop:config>
public void handleBefore(){
System.out.println("前置增强方法--取款操作前的用户校验");
}
后置增强
<aop:after-returning method="handleAfter" pointcut-ref="myPointCut"/>
public void handleAfter(){
System.out.println("后置增强方法--取款后的信息输出");
}
环绕增强
<aop:around method="around" pointcut-ref="myPointCut"/>
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("检查前。。。");
pjp.proceed();//调用切点方法
System.out.println("检查后。。。");
}
异常增强
在业务目标方法中出现类异常情况,则会执行异常增强,如果不存在异常,则不执行异常增强
<aop:after-throwing method="excep" pointcut-ref="myPointCut"/>
public void excep(){
System.out.println("出错啦");
}
最终增强
不管有没有异常出现,均会执行的增强称之为最终增强
<aop:after method="finallyHandle" pointcut-ref="myPointCut"/>
public void finallyHandle(){
System.out.println("最终增强--关闭资源");
}
- 测试类
@Test
public void test1(){
ApplicationContext context = new
ClassPathXmlApplicationContext("spring/applicationContext.xml");
TargetClass target = (TargetClass) context.getBean("target");
target.getMoney();
}
- 基于注解版
- 修改核心配置文件,加入注解驱动
<!-- 开启spring注解驱动 -->
<context:component-scan base-package="com.kgc.anno"></context:component-scan>
<!-- 开启aop切面注解驱动(aop执行自动动态代理)-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2.注意事项:
- 目标类要设置@service注解,目的是为了在调用service时候完成实例化和注入操作
- 增强类要设置@Aspect切面注解,目的是定义当前类是切面,而且也要设置@service注解,目的也是为了在完
成实例化和注入操作 - 注意:注解开发,主要更改的是增强类里的注解配置
3.增强类
@Service // 实例化 增强类
@Aspect // @Aspect 表示 增强类 为切面
public class HandleClass {
//前置增强
@Before("execution(* com.kgc.anno.TargetClass.getMoney(..))")
public void handleBefore(){System.out.println("注解版前置增强方法--取款操作前的用户校验");
}
//后置增强
@AfterReturning("execution(* com.kgc.anno.TargetClass.getMoney(..))")
public void handleAfter(){
System.out.println("注解版后置增强方法--取款后的信息输出");
}
//环绕增强
@Around("execution(* com.kgc.anno.TargetClass.getMoney(..))")
public void around(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("注解版检查前。。。");
pjp.proceed();//调用切点方法
System.out.println("注解版检查后。。。");
}
//异常增强
@AfterThrowing("execution(* com.kgc.anno.TargetClass.getMoney(..))")
public void excep(){
System.out.println("注解版出错啦");
}
//最终增强
@After("execution(* com.kgc.anno.TargetClass.getMoney(..))")
public void finallyHandle(){
System.out.println("注解版最终增强--关闭资源");
}
}
4.目标类
@Service//实例化 目标类
public class TargetClass {
public void getMoney(){
System.out.println("目标方法:取款!");
// int i=1/0;
}
}
5.测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/spring/applicationContext.xml")
public class TestAop {
@Autowired
TargetClass target;
@Test
public void test1(){
target.getMoney();
}
}
后面会讲解Spring的事务管理