Spring AOP 复习
Aspect Oriented Programming
通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,利用aop可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低
作用:在程序运行期间,不修改源码对已有方法进行增强
优势:减少重复代码,提高开发效率,维护方便
SpringAOP即通过配置的方式实现aop
joinpoint连接点 指被拦截的点,在spring中指方法
pointcut切入点 被增强的方法
advice通知 拦截到joinpoint后要做的事
前置通知:切入点之前的逻辑
后置通知:切入点正常执行之后的逻辑
异常通知:catch中的逻辑
最终通知:finally中的逻辑
环绕通知:整个被加强后的方法(包括各通知和切入点)
introduction引介 一种特殊的通知,在不修改类代码的前提下在运行期为类动态地添加一些方法或field
target目标对象 被代理的对象
weaving织入 把增强应用到目标对象来创建新的代理对象的过程,spring采用动态代理织入
proxy代理 一个类被aop织入增强后,就产生一个结果代理类
aspect切面 是切入点和通知(引介)的结合
应用
a. 开发阶段
编写核心业务代码 --> 把公用代码抽取出来制成通知 --> 在配置文件中声明切入点和通知之间的关系
b. 运行阶段
Spring框架监控切入点方法的执行,一旦监控到切入点方法被运行,使用代理机制,动态创建目标对旬的代理对象,根据通知类别,在代理对象的对应位置,将通知对应的功能织入
xml
- 建立maven工程,添加依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.7</version>
</dependency>
- 编写核心业务类及方法(如业务层接口)
public class AccountServiceImpl implements AccountService{
void saveAccount(){
System.out.println("saving...")
}
}
- 编写提供公共代码的类
public class advice{
public void preMethod(){...}; }
- 在resources包下编写配置文件bean.xml,并导入约束
<?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>
- 配置spring ioc,把service对象配置进容器
<bean id="accountService" class="包路径.AccountServiceImpl"></bean>
- 把通知类配置成bean
<bean id="advice" class="包路径.Advice"></bean>
- 配置切面
<aop:config>
<aop:aspect id="advice" ref="advice">
<aop:before method="preMethod" pointcut="* com.domain.service.impl.*.*(..)"></aop:before>
</aop:aspect>
</aop:config>
aop:config标签表明开始aop的配置
aop:aspect标签表明配置切面
id属性提供切面的唯一标识
ref属性指定通知类beanId
aop:before标签表示前置通知
method属性用于指定方法
pointcut属性用于通过切入点表达式指定对哪些方法进行增强
(before前置, after-returning后置, after-throwing异常, after最终)
切入点表达式 (用导入的aspectJ依赖解析)
访问修饰符 返回值 包名.包名.包名...类名.方法名(参数列表)
访问修饰符可以省略,返回值、包名、类名、方法名、参数类型可以用通配符*表示任意(但必须有,一个通配符对应一个),包名可以使用..表示当前包及其子包,参数列表可以只写数据类型,
参数列表可以用..表示任意个数的参数
通常写法:* com.domain.service.impl.星.星(..)
aop:pointcut标签用于指定切入点表达式,属性id和expression,配在aop:aspect外面则可以在其后的切面都可以通过pointcut-ref属性使用
- 配置环绕通知
<aop:around method="aroundMethod" pointcut-ref="pointcutId"></aop:around>
//环绕通知: 即spring提供的一种在代码中手动设置增强代码的方式,而不需要挨个配置
public Object arountMethod(ProceedingJoinPoint pjp){
//ProceedingJoinPoint接口由spring提供
Object returnValue = null
try{
preMethod(); //前置通知
Object[] args = pjp.getArgs(); //获取参数
returnValue = pjp.proceed(args); //明确调用业务层方法
afterReturningMethod(); //后置通知
return returnValue;
} catch(Throwable t){ //不能写Exception
afterThrowingMethod(); //异常通知
throw new RuntimeException(t);
} finally{
afterMethod(); //最终通知
}
}
注解
2.3.4.同xml方式
bean.xml中配置
要扫描的包
开启spring注解AOP支持(可以在配置类上用@EnableAspectJAutoProxy替代)
<context:component-scan base-package="com.domain"></context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
将AccountServiceImpl和Advice放入ioc容器
Advice类上加@Aspect
配置切入点表达式
在Adive类中新加私有方法private void ptId(),在其上加@Pointcut("execution(切入点表达式)")
在通知方法上加注解@Before("ptId()") @AfterReturning("ptId()") @Afterthrowing("ptId()") @After("ptId()") @Around("ptId()")
ptId()括号不能少
- 注解aop的各通知顺序可能会发生错乱,所以推荐使用环绕通知
Spring 事务控制(声明式)
事务处于业务层,有四大特性
(1)原子性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
(2)一致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
(3)隔离性:隔离状态执行事务,使它们好像是系统在给定时间内执行的唯一操作。如果有两个事务,运行在相同的时间内,执行 相同的功能,事务的隔离性将确保每一事务在系统中认为只有该事务在使用系统。这种属性有时称为串行化,为了防止事务操作间的混淆, 必须串行化或序列化请 求,使得在同一时间仅有一个请求用于同一数据。
(4)持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
导入jar包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.0.2.RELEASE</version>
</dependency>
spring提供PlatformTransactionManager接口,里面提供commit()和rollback()方法
常用的实现类:DataSourceTransactionManager(常用)或HibernateTransactionManager(专用)
XML
导入约束
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
配置数据源
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/day04_spring"/>
<property name="username" value="root"/>
<property name="password" value="root"/>
</bean>
配置业务层类和持久层类
<bean id="accountDao" class="全限定类名">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="accountService" class="全限定类名">
<property name="accountDao" ref="accountDao"></property>
</bean>
配置事务管理器
<bean id="transactionManager" class="org.spring.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref=dataSource></property>
</bean>
配置事务通知
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED" read-only="false"/>
<!-- 部分匹配优先级更高-->
<tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
</tx:attributes>
</tx:advice>
isolation="" 隔离级别:默认使用数据库的默认隔离级别
propagation="" 传播行为:默认REQUIRED,表示一定会有事务,查询用SUPPORTS
read-only="" 是否只读:默认false,只有查询设为true
rollback-for="" 指定异常:产生该异常时回滚,其他异常不回滚,不设定表示全回滚
no-rollback-for="" 指定异常:产生该异常时不回滚,其他异常回滚,不设定表示全回滚
timeout="" 超时时间:默认-1,永不超时,以秒为单位配置AOP
<aop:config>
<!-- 配置切入点表达式 -->
<aop:pointcut id="pt1" expression="execution(* com.whteway.service.impl.*.*(..))"/>
<!-- 建立切入点与事务通知的对应关系 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pt1"/>
</aop:config>
注解
配置事务管理器
开启spring对注解事务的支持
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
//创建事务管理器的配置类和DataSource的配置类
public class TransactionConfig{
@Bean(name="transactionManager")
public PlatformTransactionManager createTransactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
//在主配置类上加@EnableTransactionManagement
// 和@Import({DataSourceConfig.class, TransactionConfig.class})
在需要事务支持的地方(类或方法)使用@Transactional
原理
对象的配置来决定。默认的策略是如果目标类是接口, 则使用JDK动态代理技术,否则使用Cglib来生成代理。
JDK 动态接口代理
- JDK 动态代理主要涉及到 java.lang.reflect 包中的两个类:Proxy 和 InvocationHandler。 InvocationHandler是一个接口,通过实现该接口定义横切逻辑,并通过反射机制调用目标类 的代码,动态将横切逻辑和业务逻辑编制在一起。Proxy 利用 InvocationHandler 动态创建 一个符合某一接口的实例,生成目标类的代理对象。
13/04/2018 Page 131 of 283
CGLib 动态代理
- :CGLib全称为Code Generation Library,是一个强大的高性能,高质量的代码生成类库, 可以在运行期扩展 Java 类与实现 Java 接口,CGLib 封装了 asm,可以再运行期动态生成新 的 class。和 JDK 动态代理相比较:JDK 创建代理有一个限制,就是只能为接口创建代理实例, 而对于没有通过接口定义业务方法的类,则可以通过CGLib创建动态代理。
Spring AOP 复习的更多相关文章
- Spring AOP复习
最近在翻<Spring In Action>Spring 实战这本书,重新了解了一下AOP的概念和思想并写了一个小Demo示例,记录在这里: 环境:intelliJ IDEA 2018.M ...
- Spring技术内幕:Spring AOP的实现原理(二)
**二.AOP的设计与实现 1.JVM的动态代理特性** 在Spring AOP实现中, 使用的核心技术时动态代理.而这样的动态代理实际上是JDK的一个特性.通过JDK的动态代理特性,能够为随意Jav ...
- Spring AOP 和 AspectJ
现如今有许多个可用的 AOP 库,使用这些库需要能够回答以下问题: 是否与现有的或新的应用程序兼容? 在哪里可以使用 AOP ? 如何迅速与应用程序集成? 性能开销是多少? 在本文中,我们将回答这些问 ...
- Spring知识点复习
Spring知识点复习 一.专业术语 侵入式设计 引入框架,对现有的类的结构有影响,即需要实现或继承某些特定类.如:Struts框架 非侵入式设计 引入框架,对现有的类结构没有影响.如:Hiberna ...
- 运用Spring Aop,一个注解实现日志记录
运用Spring Aop,一个注解实现日志记录 1. 介绍 我们都知道Spring框架的两大特性分别是 IOC (控制反转)和 AOP (面向切面),这个是每一个Spring学习视频里面一开始都会提到 ...
- 学习AOP之深入一点Spring Aop
上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...
- 学习AOP之认识一下Spring AOP
心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...
- spring aop
什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...
- spring aop注解方式与xml方式配置
注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...
随机推荐
- BareTail(日志查看工具)
官网:http://www.baremetalsoft.com/baretail/index.php 在看log文件时,当日志有新增时,会自动滚动到最新的那一行,对于查看实时日志有作用.
- 【JavaScript】BOM对象——Window对象&History对象&Location 对象
1.Window对象: 表示浏览器中打开的窗口 setInterval():它有一个返回值,主要是提供给 clearInterval 使用. setTimeout():它有一个返回值,主要是提供给 c ...
- 重复的DNA序列[哈希表] LeetCode.187
所有 DNA 由一系列缩写为 A,C,G 和 T 的核苷酸组成,例如:"ACGAATTCCG".在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助. 编写一个函数 ...
- redisTemplate 键值序列化策略
redisTemplate 键值序列化策略 RedisSerializer<T> StringRedisSerializer JdkSerializationRedisSerializer ...
- 【java异常】redis.clients.jedis.exceptions.JedisConnectionException: Could not get a res
产生此错误的原因通常是: 一.Redis没有启动: 我自己遇到一次这样的问题.汗! 二.由于防火墙原因无法连接到Redis; 1.服务器防火墙入站规则. 2.访问Redis的应用程序所在主机的出站规则 ...
- 37 树莓派识别opencv-dnn
https://heartbeat.fritz.ai/real-time-object-detection-on-raspberry-pi-using-opencv-dnn-98827255fa60 ...
- 自用ftp上传脚本
#!/bin/sh backupserver=$1 #localdir=ftp_result_tmp username=$3 password=$4 #remodir='./Log/2018-01-2 ...
- label的作用是什么?怎么用的?
label便签用可以让用户点击文字区域,自动聚焦到当前项的input框. input设置id属性,label设置for属性,for属性的属性值为id属性值.
- redis之expire命令详解
expire是设置redis过期时间的命令,需要注意的点有以下几点 expire设置过期时间的单位是秒,如设置name的过期时间为1000秒 expire name 1000 超过时间后会自动删除 ...
- TensorFlow实现文本情感分析详解
http://c.biancheng.net/view/1938.html 前面我们介绍了如何将卷积网络应用于图像.本节将把相似的想法应用于文本. 文本和图像有什么共同之处?乍一看很少.但是,如果将句 ...