Spring AOP介绍(一)之 Spring AOP 基础介绍
Spring AOP介绍(一)之 Spring AOP 基础介绍
AOP是什么?
AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。与OOP对比,AOP面向切面,传统的OOP开发中,代码逻辑是自上而下的,在这些自上而下的过程中,会产生一些横切性的问题,这些横切性的问题和我们的主业务逻辑关系不大,会散落在代码的各个地方,造成难以维护,AOP的变成思想就是把业务逻辑和横切的问题进行分离,从而达到解耦的目的,提到代码的可重用性与开发效率。
可以看下这个图:
spring aop场景.png
AOP的应用场景有哪些?
如上图中显示的:
- 日志记录
- 权限验证
- 事务管理
- 等等
Spring对于AOP是怎样实现的呢?
- JDK动态代理(接口实现)
JDK原生动态代理是Java原生支持的,不需要任何外部依赖,但是它只能基于接口进行代理
- CGLIB代理(继承)
CGLIB(Code Generation Library)是一个基于ASM的字节码生成库, 它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。
编译时期的织入还是运行时期的织入?
两者都是在运行时期织入(后面有源码介绍)
初始化时期织入还是获取对象时期织入?
通过源码分析,可以知道是在初始化时期织入(后面有源码介绍)
Spring AOP和AspectJ的关系是什么?
对于Spring AOP来说,AOP是实现的目标,AspectJ是实现的手段,类似的还有IOC(Inversion of Control 控制反转)是目标,实现的手段是DI(Dependency Injection 依赖注入)。
Spring AOP提供两种编程风格
- @AspectJ support (利用aspectj的注解)
- Schema-based AOP support (xml aop:config 命名空间)
Spring AOP应用
让我们首先了解一些AOP概念和术语。
概念 |
描述 |
---|---|
Join point(连接点) |
目标对象中的方法,类似数据库表中的一条记录 |
PointCut(切点) |
表示连接点的集合,类似数据库中的表 |
Advice(通知) |
通知指的就是指拦截到连接点之后要执行的代码,通知分为前置、后置、异常、最终、环绕通知五类 |
Aspect(切面) |
切点、连接点、通知等的载体,它们加起来就是一个切面 |
Target object(目标对象) |
包含连接点的对象,也被称作被通知或被代理对象 |
AOP proxy(AOP 代理对象) |
AOP创建的对象,包含通知 |
Weaving(织入) |
把代理逻辑加入到目标对象的过程,叫做织入 |
Before advice(前置通知) |
前置通知 |
After returning advice(后置通知) |
后置通知 |
Around advice(环绕通知) |
前后都有,最常用的一种通知 |
简单代码演示
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.demo.spring</groupId>
<artifactId>spring-aop</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>spring-aop Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.9</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
com.demo.spring.dao.TestDao
package com.demo.spring.dao;
import org.springframework.stereotype.Component;
/**
* PACKAGE_NAME
*
* @author Zyy
* @date 2019/3/4 23:03
*/
@Component
public class TestDao {
public void query(){
System.out.println("dao-query ...");
}
}
com.demo.spring.config.AppConfig
package com.demo.spring.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
/**
* com.demo.spring.config
*
* @author Zyy
* @date 2019/3/4 23:05
*/
@Configuration
@EnableAspectJAutoProxy
@ComponentScan("com.demo.spring")
public class AppConfig {
}
com.demo.spring.config.AspectJTest
package com.demo.spring.config;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
/**
* com.demo.spring.config
*
* @author Zyy
* @date 2019/3/4 23:36
*/
@Aspect
@Component
public class AspectJTest {
@Pointcut("execution(* com.demo.spring.dao.*.*(..))")
public void pointCut(){
System.out.println("point cut");
}
@After("com.demo.spring.config.AspectJTest.pointCut()")
public void after(){
System.out.println("after advice");
}
@Before("com.demo.spring.config.AspectJTest.pointCut()")
public void before(){
System.out.println("before advice");
}
}
com.demo.spring.test.AopTest
package com.demo.spring.test;
import com.demo.spring.config.AppConfig;
import com.demo.spring.dao.TestDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* com.demo.spring.test
*
* @author Zyy
* @date 2019/3/4 23:07
*/
public class AopTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
TestDao dao = context.getBean(TestDao.class);
dao.query();
}
}
运行结果:
before advice
dao-query ...
after advice
欢迎留言进行讨论:) 我的博客即将同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=16n5qvyzybi7j
- JS魔法堂:jQuery.Deferred(jQuery1.5-2.1)源码剖析
- 一步一步学习Bootstrap系列--表单布局
- Java进阶01 String类
- linux(十二)之用户管理
- Dapper.Net 应用
- linux(十)配置ssh免密登录实现
- 微信群也有群相册功能了,终于可以给手机相册腾出空间了!
- PHP5.3、PHP5.4安装ZendOptimizer
- linux(十一)之初始化文件
- C编译: 动态连接库 (.so文件)
- 腾讯叮当首都发布生态合作伙伴计划,全面开放AI能力
- Python火爆的背后的应用领域是数据挖掘、大数据和人工智能的应用吗?
- linux(九)之网络基础
- eclipse从数据库逆向生成Hibernate实体类
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Android Glide加载网络图片不显示,但用网页打开又正常显示
- Android获取APP的版本号和版本名
- Android 在一个APP里打开另一个APP
- Android 自定义加载动画Dialog弹窗
- Android 天气APP(十一)未来七天的天气预报、逐小时预报、UI优化
- Android 天气APP(十)继续优化、下拉刷新页面天气数据
- Activity 活动跳转(Java&Kotlin)
- Android 天气APP(九)细节优化、必应每日一图
- Android CheckBox修改选中颜色并去除选中时的水波纹效果
- 绘制带回归线的散点图
- Java&Android像素px、dip转换工具类
- Android WIFI是否连接,网络状态监测工具类
- Kotlin学习日志(五)类与对象
- Android 应用横屏运行
- Android 修改EditView输入框的光标颜色