基于标注的AOP面向切面编程
1.什么是AOP
Aspect Orientied Programming的简称,即 面向(方面)切面编程 ,不改变一个组件源代码的情况下 可以对组件功能进行增强。
例如:servlet中的过滤器,继承,装饰者模式,代理模式,
JDK 的代理 必须有统一接口 目标类和代理类 兄弟关系
CGLIB 的代理 底层是继承 目标类和代理类 父子关系
2.AOP 中涉及到核心概念
###切面 Aspect 抽取共通业务逻辑到一个类中 每个共通业务逻辑就是一个切面方法
定义了共通业务逻辑的类叫切面类 使用切面类创建的对象 叫切面对象
连接点 JoinPoint 添加切面逻辑的一个位置 一般这个就是一个方法
###切点 Pointcut 一堆连接点的集合 后面会讲表达式的写法
目标对象 Target 那个对象需要加共通业务逻辑
代理对象 Proxy 被增强了的目标对象就是代理对象
###通知 Advice 时机 (目标方法执行之前 之后 执行前后 出异常)
切面 通知 切点 (把共通的业务逻辑 在合适的时间点 加入到对应的方法上)
6.切点表达式的写法
6.1 bean 名字限定表达式
bean(容器中组件的id) 组件的id可以使用统配
6.2 类型限定表达式
within(限定的类型) 限定的类型 是通过包名.类名
within(com.xdl.service.XdlUserService) 对 XdlUserService 类型做限定
XdlUserService中所有方法都切入共通逻辑
within(com.xdl.service.*) 对service 包下 所有类型 都切入对应的逻辑
within(com.xdl.*.*) xdl 直接子包下的类型 切入对应的逻辑
within(com.xdl..*) xdl 包 以及子包下的类型 切入对应的逻辑
6.3 方法限定表达式
execution(权限修饰 方法返回值类型 方法名(参数) throws 异常)
返回值类型 方法名(参数) 是必须的
execution(void user*()) 所有的返回void 方法名以user开头的无参的方法
被切入逻辑
7.通知的五种类型
<aop:before 前置通知 目标方法执行之前执行
<aop:after 最终通知 目标方法执行之后 最终肯定会执行
<aop:after-returning 后置通知 目标方法执行之后 如果目标方法出现异常 则不执行
<aop:after-throwing 异常通知 目标方法执行出现异常 就会调用异常通知
<aop:around 环绕通知 目标方法执行前后都会调用
8. 五种通知对应的标注
<aop:before 前置通知 @Before
<aop:after 最终通知 @After
<aop:after-returning 后置通知 @AfterReturning
<aop:after-throwing 异常通知 @AfterThrowing
<aop:around 环绕通知 @Around
例子:
首先拷贝一个配置文件到类路径下
<?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:jdbc="http://www.springframework.org/schema/jdbc" xmlns:jee="http://www.springframework.org/schema/jee"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util"
xmlns:jpa="http://www.springframework.org/schema/data/jpa"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-4.1.xsd
http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa-1.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd">
<!-- 组件扫描 -->
<context:component-scan base-package="cn.com"></context:component-scan>
<!-- 通过配置织入@Aspectj切面-->
<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans>
好了,开始写代码:
首先添加一个model类;
import java.io.Serializable;
public class BankAccountModel implements Serializable {
private static final long serialVersionUID = 1L;
private int id;
private String acc_no;
private String acc_password;
private double acc_money;
public BankAccountModel() {
super();
}
public BankAccountModel(int id, String acc_no, String acc_password, double acc_money) {
super();
this.id = id;
this.acc_no = acc_no;
this.acc_password = acc_password;
this.acc_money = acc_money;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAcc_no() {
return acc_no;
}
public void setAcc_no(String acc_no) {
this.acc_no = acc_no;
}
public String getAcc_password() {
return acc_password;
}
public void setAcc_password(String acc_password) {
this.acc_password = acc_password;
}
public double getAcc_money() {
return acc_money;
}
public void setAcc_money(double acc_money) {
this.acc_money = acc_money;
}
public static long getSerialversionuid() {
return serialVersionUID;
}
@Override
public String toString() {
return "BankAccountModel [id=" + id + ", acc_no=" + acc_no + ", acc_password=" + acc_password + ", acc_money="
+ acc_money + "]";
}
}
来一个接口和一个实现类
public interface BankAccountDao {
int addAccount(BankAccountModel ba);//添加
BankAccountModel selectAccountByID(int id); //查询
}
@Repository("bankDao")//持久层标注
public class BankAccountDaoIMP implements BankAccountDao {
@Override
public int addAccount(BankAccountModel ba) {
System.out.println("正在添加......");
return 0;
}
@Override
public BankAccountModel selectAccountByID(int id) {
System.out.println("正在查询......");
return null;
}
}
然后再写一个service层,(好吧,其实是可以不用写的,毕竟没有真正实现功能)
@Service("bankService")//spring中service层的标注1
public class BankAccountService {
@Autowired
private BankAccountDao dao;
public int addAccount(BankAccountModel ba) {
return dao.addAccount(ba);
}
public BankAccountModel selectAccountByID(int id) {
return dao.selectAccountByID(id);
}
public void login(){
System.out.println("登录中....");
if(1==2){
throw new RuntimeException("登录方法出现异常!!");//这一部分未来测试专门让他出异常的,可以忽略哦
}
}
public void register(){
System.out.println("正在注册....");
}
}
最后可以来一个aspect类了
@Component//通用层标注
@Aspect //基于aop的标注
public class BankAccountAspect { /*
* @Before("bean(bankA*)") public void beforeUserLog(){ System.out.println(
* "#### ####"); }
*/ @Before("within(cn.com.service..*)")
public void beforeUserLog() {
System.out.println("#### ####");
} /* 异常的参数必须出现在最后面 */
@AfterThrowing(pointcut = "within(cn.com.service..*)", throwing = "e")
public void beforeAround(JoinPoint j, Exception e) {
System.out.println("正在记录异常信息..." + e.getMessage() + ":" + j.getSignature());
} /*统计方法执行时间*/
@Around("execution(void *())")
public Object countTime(ProceedingJoinPoint pjp) throws Throwable{//此处的方法必须返回为Object,否则环绕的目标方法中如果有返回值就会丢弃
long stat=System.currentTimeMillis();
//执行目标方法
Object proceed = pjp.proceed();//使用proceed()方法来执行目标方法 long end = System.currentTimeMillis();
System.out.println("方法执行的毫秒数是:" + (end-stat));
return proceed;
} } 测试代码:
public static void main(String[] args) {
ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");
BankAccountService user=app.getBean("bankService",BankAccountService.class);
System.out.println(user.addAccount(new BankAccountModel(12, "13", "12324", 123)));
System.out.println(user.selectAccountByID(2));
}
测试结果:
#### ####
正在添加......
0
#### ####
正在查询......
null
基于标注的AOP面向切面编程的更多相关文章
- 基于SpringBoot AOP面向切面编程实现Redis分布式锁
基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式 ...
- 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...
- Spring:AOP面向切面编程
AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...
- 详细解读 Spring AOP 面向切面编程(二)
本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...
- Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存
本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...
- 03-spring框架—— AOP 面向切面编程
3.1 动态代理 动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由 JVM 根据反射等机制动态生成的.代理对象与目标 ...
- AOP(面向切面编程)大概了解一下
前言 上一篇在聊MemoryCache的时候,用到了Autofac提供的拦截器进行面向切面编程,很明显能体会到其优势,既然涉及到了,那就趁热打铁,一起来探探面向切面编程. 正文 1. 概述 在软件业, ...
- 极简SpringBoot指南-Chapter05-SpringBoot中的AOP面向切面编程简介
仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...
- AOP 面向切面编程, Attribute在项目中的应用
一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...
随机推荐
- 【总结】 BZOJ1000~1099板刷计划
Tham又布置了一大堆题目,但是因为我TCL完全不会做,所以只能切切BZOJ的题目,划划水,要不是xz的面子大,我就已经被赶出了CJ信息组了QwQ(聂已己是神仙!) 1000 A+B这种入门题就不用写 ...
- kolla-ansible安装openstack(Ocata)
基本功能部署 基础环境 角色 操作系统 硬件配置 Depoly CentOS 7 Server 磁盘:40GB 内存:8GB 网卡:ens3(内网) ens4(外网) Sched CentOS 7 S ...
- k8s 入门系列之介绍篇
•Kubernetes介绍1.背景介绍 云计算飞速发展 - IaaS - PaaS - SaaS Docker技术突飞猛进 - 一次构建,到处运行 - 容器的快速轻量 - 完整的生态环境2.什么是ku ...
- ClamAV学习【3】——scanmanager函数浏览
吃饱饭继续浏览Manager.c的scanmanager函数,这个函数的功能吧,暂时理解如下. 接收一个命令行参数(经过处理的optstruct结构指针). 然后根据选项判断文件类型种类,还有一些扫描 ...
- “全栈2019”Java第九十四章:局部内部类详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 查看inux系统类型和版本
当我们使用一台新的linux服务器的时候,为了区分他们的命令,我们首先第一步就是要搞清楚这个系统的类型和版本号,据此再来使用对应的命令. 下面来看看可以使用以下基本命令来查看 Linux 发行版名称和 ...
- JSP入门之自定义标签
第二部分简单讲解:主要讲解el表达式,核心标签库.本章主要讲解:自定义标签库:404页面,505页面,错误页面配置方法 全部代码下载:链接 1.JSP自定义标签: 自定义标签是用户定义的JSP语言元素 ...
- 39.oracle高级篇
标题说是高级篇,其实也就是相对于基础篇来说的,也不是很深奥,自己平时工作中也都会用到,这里回忆的并不是特别冷门的知识,不要掉以轻心,以为“高级”就觉得工作中不会用到了. 一.select into 和 ...
- 解压命令tar zxvf中zxvf的意思
x : 从 tar 包中把文件提取出来 z : 表示 tar 包是被 gzip 压缩过的,所以解压时需要用 gunzip 解压 v : 显示详细信息 f xxx.tar.gz : 指定被处理的文件是 ...
- mvvm小论(暂记)
广州-PC26(34627) 2:09:44 在android 线程最后用 handler = new Handler(); updateThread = new Runnabl ...