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 ...
随机推荐
- XGBoost 参数介绍
XGBoost 的设置有三种参数:一般参数,提升参数和学习参数. 一般参数 取决于提升器,通常是树或线性模型提升参数 取决于选择的提升器的相关参数学习参数 取决于指定学习任务和相应的学习目标一般参数 ...
- frame标签和frameset
框架: 属性 值 描述 frameborder 0 1 规定是否显示框架周围的边框. longdesc URL 规定一个包含有关框架内容的长描述的页面. marginheight pixels 定义框 ...
- java接口顺口溜
原创作品,转载请注明来源,这篇博客我也发到了我的csdnhttps://blog.csdn.net/suyues/article/details/103458086 接口 接口定义全局变量和抽象方法 ...
- 逆向破解之160个CrackMe —— 023-024
CrackMe —— 023 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...
- 使用cookiecutter创建django项目
使用cookiecutter创建django项目 下载安装: pip install cookiecutter cookiecutter https://github.com/pydanny/cook ...
- Wpf DataGrid动态添加列,行数据(一)
由于最近有这方面的需求,而且刚接触wpf不久,在网上找了很多方法,都不是使用MVVM模式的,因为DataGrid的列不能绑定 这就难受了,我想了个折中的方法,这个是使用了MVVMLight的消息机制, ...
- flask-restful在解析的请求一定要传content-type:application/json吗?答:其实不需要!
在处理flask-restful api请求时,因为postman发送的格式为text,没有携带content-type:application/json,在解析参数的时候,参数的值都给搞成了空,导致 ...
- MySQL体系结构与存储引擎
MySQL 体系结构 先看 MySQL 数据库的体系结构,如下图所示. MySQL 体系结构由 Client Connectors 层.MySQL Server 层及存储引擎层组成. Client C ...
- MapReduce running in uber mode (jvm重用)
原文 http://blog.csdn.net/samhacker/article/details/15692003 yarn-site.xml 主要是这几个参数 - mapreduce.job.u ...
- LeetCode 348. Design Tic-Tac-Toe
原题链接在这里:https://leetcode.com/problems/design-tic-tac-toe/ 题目: Design a Tic-tac-toe game that is play ...