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 ...
随机推荐
- c++ c的拓展
C++对c的拓展之, 引用和const关键字 bool类型关键字 C++中的布尔类型 C++在C语言的基本类型系统之上增加了bool C++中的bool可取的值只有true和false 理论上bool ...
- Latex 调整断字,连接符,取消断词/断字
latex使用了处理断字的算法去自动的找断字的地方,而且latex会调整单词间距,使得文章看起来不会显得疏密不一致.大多数情况下,这些算法都工作得很好.但是因为断字的算法是根据某种规则来处理单词的断字 ...
- 踩iviewui中Select 选择器两级联动,重置查询条件时第二级数据无法清除的坑
小颖公司最近做的项目用的vue+iviewui+axios,在做项目的过程中,遇到一个问题: 二级联动的下拉框,第一个下拉框一直都有值,第二个下拉框是在选择了第一个下拉框之后采取调用ajax获取其值, ...
- 洛谷p2827蚯蚓题解
题目 算法标签里的算法什么的都不会啊 什么二叉堆?? qbxt出去学习的时候讲的,一段时间之前做的,现在才写到博客上的 维护3个队列,队列1表示最开始的蚯蚓,队列2表示每一次被切的蚯蚓被分开的较长的那 ...
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06) 题解
昨晚恶补了一下二叉堆的内容 然后就找了几个二叉堆的题来做awa 然后发现用二叉堆做这题复杂度是O(nlogn) 但是有O(n)的解法 (某大佬这么说) 思路大概就是: 利用一个大根堆一个小根堆来维护第 ...
- 洛谷 p3870 开关 线段树模板
这两天学了很长时间于是做了一道水题 我就用了模板,就连任何优化都没有 就AC了,复杂度也很爆炸10个点1500多毫秒 这个题就是把lazy[]改成记录下修改的次数,每次修改的时候mod 2,因为反过来 ...
- PATA1055 The World's Richest (25 分)
1055 The World's Richest (25 分) Forbes magazine publishes every year its list of billionaires based ...
- ros ap 的无线中继
https://wiki.mikrotik.com/wiki/Manual:Interface/Wireless#Repeater Wireless repeater will allow to re ...
- Docker环境下的前后端分离项目部署与运维(八)使用Docker部署RabbitMQ集群
下载RabbitMQ镜像 镜像地址RabbitMQ Docker官方认证镜像地址:https://hub.docker.com/_/rabbitmq 安装命令安装之前,切记把Docker Hub设置为 ...
- Vue.js之入门
1.What is Vue.js? Vue.js(读音 /vjuː/, 类似于 view) 是一套构建用户界面的 渐进式框架,通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件. 2.引入 ...