实在是秒啊,我还从来没见过把Spring之AOP讲的这么通俗易懂的,安排!
Spring之AOP
什么是AOP?
AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
目的:
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
作用及其优势
作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强
优势: 减少重复代码,提高开发效率,并且便于维护
AOP 的底层实现
AOP 的底层是通过 Spring 提供的的动态代理技术实现的。在运行期间,Spring通过动态代理技术动态的生成代理对象,代理对象方法执行时进行增强功能的介入,在去调用目标对象的方法,从而完成功能的增强。
AOP 的动态代理技术
JDK 代理 : 基于接口的动态代理技术
cglib 代理:基于父类的动态代理技术
JDK 的动态代理
①目标类接口
public interface TargetInterface {
public void method();
}
②目标类
public class Target implements TargetInterface {
@Override
public void method() {
System.out.println("Target running....");
}
}
③动态代理代码
Target target = new Target(); //创建目标对象
//创建代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(target.getClass()
.getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println("前置增强代码...");
Object invoke = method.invoke(target, args);
System.out.println("后置增强代码...");
return invoke;
}
}
);
④ 调用代理对象的方法测试
// 测试,当调用接口的任何方法时,代理对象的代码都无需修改
proxy.method();
cglib 的动态代理
①目标类
public class Target {
public void method() {
System.out.println("Target running....");
}
}
②动态代理代码
Target target = new Target(); //创建目标对象
Enhancer enhancer = new Enhancer(); //创建增强器
enhancer.setSuperclass(Target.class); //设置父类
enhancer.setCallback(new MethodInterceptor() { //设置回调
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("前置代码增强....");
Object invoke = method.invoke(target, objects);
System.out.println("后置代码增强....");
return invoke;
}
});
Target proxy = (Target) enhancer.create(); //创建代理对象
③调用代理对象的方法测试
//测试,当调用接口的任何方法时,代理对象的代码都无需修改
proxy.method();
相关知识要点
aop:面向切面编程
aop底层实现:基于JDK的动态代理 和 基于Cglib的动态代理
aop的重点概念:
Pointcut(切入点):被增强的方法 Advice(通知/ 增强):封装增强业务逻辑的方法 Aspect(切面):切点+通知 Weaving(织入):将切点与通知结合的过程
开发明确事项:
谁是切点(切点表达式配置) 谁是通知(切面类中的增强方法) 将切点和通知进行织入配置
基于XML配置文件的AOP开发
①导入 AOP 相关坐标
<!--导入spring的context坐标,context依赖aop-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<!--spring测试的依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.2.5.RELEASE</version>
</dependency> <!-- aspectj的织入 -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.2</version>
</dependency>
②创建目标接口和目标类(内部有切点)
public interface TestService {
public void save();
}
public class TestServiceImpl implements TestService {
public void save() {
System.out.println("save方法runnning......");
}
}
③创建切面类(内部有增强方法)
public class Advice {
//前置增强的通知
public void before(){
System.out.println("前置增强......");
}
}
④将目标类和切面类的对象创建权交给 spring
<!--配置目标类-->
<bean id="testService" class="com.duanping.service.impl.TestServiceImpl"></bean> <!--配置切面类-->
<bean id="advice" class="com.duanping.advices.Advice"></bean>
⑤在 applicationContext.xml 中配置织入关系
导入aop命名空间
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd ">
配置切点表达式和前置增强的织入关系
<!--配置织入: 告诉spring框架 哪些方法(切点)需要进行哪些增强(前置、后置....) -->
<aop:config> <!-- 声明切面 引入advice的bean作为切面对象-->
<aop:aspect ref="advice">
<!--切面: 通知+切点 配置对切点的方法进行前置增强-->
<aop:before method="before" pointcut="execution(public void com.duanping.service.impl.TestServiceImpl.save())"></aop:before>
</aop:aspect>
</aop:config>
⑥测试代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest { @Autowired
private TestService testService; @Test
public void test1(){ testService.save();
}
}
⑦测试结果

XML 配置 AOP 详解
1) 切点表达式的写法
表达式语法:
execution([修饰符] 返回值类型 包名.类名.方法名(参数))
访问修饰符可以省略
返回值类型、包名、类名、方法名可以使用星号* 代表任意
包名与类名之间一个点 . 代表当前包下的类,两个点 … 表示当前包及其子包下的类
参数列表可以使用两个点 … 表示任意个数,任意类型的参数列表
例如:
execution(public void com.itheima.aop.Target.method())
execution(void com.itheima.aop.Target.*(..))
execution(* com.itheima.aop.*.*(..))
execution(* com.itheima.aop..*.*(..))
execution(* *..*.*(..))
2) 通知的类型
通知的配置语法:
<aop:通知类型 method=“切面类中方法名” pointcut=“切点表达式"></aop:通知类型>

3) 切点表达式的抽取
当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替 pointcut 属性来引用抽取后的切点表达式。
<!--对切点的抽取-->
<aop:pointcut id="point" expression="execution(* com.duanping.service.impl.*.*(..))"/> <aop:before method="before" pointcut-ref="point"></aop:before>
基于注解的 AOP 开发
在配置文件中开启组件扫描和 AOP 的自动代理
<!--组件扫描-->
<context:component-scan base-package="com.itheima.aop"/> <!--aop的自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
注解配置 AOP 详解
1) 注解通知的类型
通知的配置语法:@通知注解(“切点表达式")
2) 切点表达式的抽取

同 xml配置
aop 一样,我们可以将切点表达式抽取。抽取方式是在切面内定义方法,在该方法上使用@Pointcut注解定义切点表达式,然后在在增强注解中进行引用
@Pointcut("execution(* com.duanping..*.*(..))")
public void pointcut(){}
//前置增强的通知
@Before("pointcut()")
public void before(){
System.out.println("前置增强......");
}
知识要点
注解aop开发步骤
①使用@Aspect标注切面类
②使用@通知注解标注通知方法
③在配置文件中配置aop自动代理aop:aspectj-autoproxy/\
最后
大家看完有什么不懂的可以在下方留言讨论,也可以关注我私信问我,我看到后都会回答的。也可以关注我的公众号:前程有光,金三银四跳槽面试季,整理了1000多道将近500多页pdf文档的Java面试题资料,文章都会在里面更新,整理的资料也会放在里面。谢谢你的观看,觉得对你有帮助的话可以专注我点个赞支持一下!
实在是秒啊,我还从来没见过把Spring之AOP讲的这么通俗易懂的,安排!的更多相关文章
- 这是你没见过的不一样的redis
转: 这是你没见过的不一样的redis 提到Redis,大家一定会想到的几个点是什么呢? 高并发,KV存储,内存数据库,丰富的数据结构,单线程(6版本之前) 那么,接下来,上面提到的这些,都会一一给大 ...
- 超赞!12套你没见过的社交媒体 & 社交网站图标
如今,社交网络成为我们信息获取和传播的重要途径,很多网站都有把内容分享到社交媒体的功能.社交媒体图标作为向用户传递信息的重要媒介,不管是在网页还是 Web 应用程序中都非常需要.今天这篇文章和大家分享 ...
- java代码。从来没想过java里的继承是多么的难懂。如哲学
总结:实例.. 这里不加super("aaa",32); 运行:父类和子类的姓名,年龄是一样的.那这个super为什么没效果呢? 显示:class:Ji姓名是 小红年龄是:20课程 ...
- 为什么一个还没毕业的大学生能够把 IO 讲的这么好?
Java IO 是一个庞大的知识体系,很多人学着学着就会学懵了,包括我在内也是如此,所以本文将会从 Java 的 BIO 开始,一步一步深入学习,引出 JDK1.4 之后出现的 NIO 技术,对比 N ...
- 这份java多线程笔记,你真得好好看看,我还没见过总结的这么全面的
1.线程,进程和多线程 1.程序:指指令和数据的有序集合,其本身没有任何意义,是一个静态的概念 2.进程:指执行程序的一次执行过程,是一个动态的概念.是系统资源分配的单位(注意:很多多线程是模拟出来的 ...
- 初识Winform , 还好没喜欢上控制台
虽然没听的太懂, 不过还是写点东西吧. 我呢, 就跟着这本书写了个学生管理系统 前面刚会了SQLserver, 所以这个学生管理系统需要连上数据库, 毕竟学了不用天诛地灭 既然需要连接数据库, 就要用 ...
- 发现被坑了,从来没看到说java的Date一旦实例化时间就不会变了
java中使用Date对象获取系统当前时间,然而我就没看到哪篇教程告诉我说Date创建对象之后其中的时间是不会变的!!! 一开始我写了类似于下边这样的代码,希望每隔一段时间显示一次时间 Date d= ...
- 2014最后一天,好烦!这个问题从来没遇到过!网上查找了很多办法都没解决!并且no wifi 了!
org.hibernate.NonUniqueObjectException: a different object with the same identifier value was alread ...
- 国内首本免费深度学习书籍!还有人没Get么?
这本书的作者很有趣鸭. 一开篇别的不说,先跟大家讲哲学,讨论人工智能实现的可能性.摘录一些他的结论: 人工智能可以实现 自由意志并不存在 量子力学并不能证明自由意志的存在 幸福感和物质水平提高并没有绝 ...
随机推荐
- hdu6115 Factory (LCA + 倍增)
Factory Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 132768/132768 K (Java/Others)Total ...
- 浅谈ES6——ES6中let、const、var三者的区别
在了解let.const.var的区别之前,先了解一些什么是es6 Es6 全称ECMAscript 是JavaScript语言的一个标准,其实Es6本质就是JavaScript的一个版本,为什么叫E ...
- PowerShell查看历史记录
PowerShell的所有历史记录: Get-Content (Get-PSReadLineOption).HistorySavePath 顺手写了一个掉用的函数: function Get ...
- Monitor Ctrl-Break线程,有点坑
Monitor Ctrl-Break线程这个在idea中特有的线程,你了解吗?这线程可能会在你调试的时候给你带来谜一样的结果,为什么呢?请看下面的例子: 首先我们先复习一下多线程的状态(因为这个问题是 ...
- 最新主流 Markdown 编辑器推荐
Markdown ,2004年由 John Gruberis 设计和开发,是一种可以使用普通文本编辑器编写的标记语言,通过简单的标记语法,它可以使普通文本内容具有一定的格式,以下将介绍目前比较流行的一 ...
- 01 . Go框架之Gin框架从入门到熟悉(路由和上传文件)
Gin框架简介 Gin是使用Go/Golang语言实现的HTTP Web框架, 接口简洁, 性能极高,截止1.4.0版本,包含测试代码,仅14K, 其中测试代码9K, 也就是说测试源码仅5k左右, 具 ...
- ThreadLocal内存泄漏需要注意的
前段时间在网上看到了一篇关于ThreadLocal内存泄漏的文章 于是个人也研究了下ThreadLocal 对象,其原理是: ThreadLocal 定义的变量值 会存储在当前线程的一个map集合中 ...
- LoRa联盟的简介
LoRa联盟成立于2015年3月,从成立开始,LoRaWAN规范就在不断更新,从1.0.0版本已更新至1.0.2版本,目前能公开下载的事2016年7月完成的1.0.2版本,可以看到该规范的主要作者包括 ...
- 03_ubuntu samba 安装配置
03_ubuntu samba 安装配置 安装samba sudo apt install samba 修改samba配置文件 sudo vim /etc/samba/smb.conf [share] ...
- 【QT】QThread源码浅析
本章会挑出QThread源码中部分重点代码来说明QThread启动到结束的过程是怎么调度的.其次因为到了Qt4.4版本,Qt的多线程就有所变化,所以本章会以Qt4.0.1和Qt5.6.2版本的源码来进 ...