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面向切面编程的更多相关文章

  1. 基于SpringBoot AOP面向切面编程实现Redis分布式锁

    基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式锁 基于SpringBoot AOP面向切面编程实现Redis分布式 ...

  2. 从壹开始前后端分离【 .NET Core2.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    代码已上传Github+Gitee,文末有地址 上回<从壹开始前后端分离[ .NET Core2.0 Api + Vue 2.0 + AOP + 分布式]框架之九 || 依赖注入IoC学习 + ...

  3. Spring:AOP面向切面编程

    AOP主要实现的目的是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果. AOP是软件开发思想阶段性的产物,我们比较熟悉面向过程O ...

  4. 详细解读 Spring AOP 面向切面编程(二)

    本文是<详细解读 Spring AOP 面向切面编程(一)>的续集. 在上篇中,我们从写死代码,到使用代理:从编程式 Spring AOP 到声明式 Spring AOP.一切都朝着简单实 ...

  5. Z从壹开始前后端分离【 .NET Core2.0/3.0 +Vue2.0 】框架之十 || AOP面向切面编程浅解析:简单日志记录 + 服务切面缓存

    本文梯子 本文3.0版本文章 代码已上传Github+Gitee,文末有地址 大神反馈: 零.今天完成的深红色部分 一.AOP 之 实现日志记录(服务层) 1.定义服务接口与实现类 2.在API层中添 ...

  6. 03-spring框架—— AOP 面向切面编程

    3.1 动态代理 动态代理是指,程序在整个运行过程中根本就不存在目标类的代理类,目标对象的代理对象只是由代理生成工具(不是真实定义的类)在程序运行时由 JVM 根据反射等机制动态生成的.代理对象与目标 ...

  7. AOP(面向切面编程)大概了解一下

    前言 上一篇在聊MemoryCache的时候,用到了Autofac提供的拦截器进行面向切面编程,很明显能体会到其优势,既然涉及到了,那就趁热打铁,一起来探探面向切面编程. 正文 1. 概述 在软件业, ...

  8. 极简SpringBoot指南-Chapter05-SpringBoot中的AOP面向切面编程简介

    仓库地址 w4ngzhen/springboot-simple-guide: This is a project that guides SpringBoot users to get started ...

  9. AOP 面向切面编程, Attribute在项目中的应用

    一.AOP(面向切面编程)简介 在我们平时的开发中,我们一般都是面对对象编程,面向对象的特点是继承.多态和封装,我们的业务逻辑代码主要是写在这一个个的类中,但我们在实现业务的同时,难免也到多个重复的操 ...

随机推荐

  1. 部署网络存储ISCSI

    1.什么是ISCSIInternet Small Computer System Interface 互联网小型计算机接口技术,是一种将SCS存储与以太网技术相结合,可以用来在互联网中传输SCSI接口 ...

  2. 初识阿里开源诊断工具Arthas

    上个月,阿里开源了一个名为Arthas的监控工具.恰逢近期自己在写多线程处理业务,由此想到了一个问题. 如果在本机开发调试,IDE可以看到当前的活动线程,例如IntelliJ IDEA,线程是运行还是 ...

  3. pandas iterrows()

    按照行遍历,第一个是行索引,第二个是每一行,series类型.

  4. Zipper(动态规划)

    点击打开链接 描述 Given three strings, you are to determine whether the third string can be formed by combin ...

  5. WEB基础技术(汇聚页)

    WEB基础技术(汇聚页) ------------------------------------------------- WEB WEB概述 HTML CSS JavaScript JavaScr ...

  6. Python面向对象(self参数、封装)

    day24 面向对象三大特性:封装 self参数 class Bar: def foo(self, arg): print(self, arg) x = Bar() print(x) x.foo(11 ...

  7. LG的nexus5(32GB版本 - 821)-TOT-底包 可用于救砖!

    LG的nexus5(32GB版本 - 821)-TOT-底包 底层修复效果完美,通过LGflashTool1.8直接刷进去就行~ 底包下载: https://pan.baidu.com/s/1Z5WD ...

  8. 处理序列的几个小技巧:保持原序去重,命名切片以及Counter类

    一. 去重并保持原来元素的顺序 def dedupe(items): h = [] for item in items: if item not in h: h.append(item) return ...

  9. Dreamweaver_CS6安装及破解文件

    资源下载地址: 链接: https://pan.baidu.com/s/1mhQ5DoO 密码: mnv3 1.下载,安装,先作为试用版安装 可能显示的页面不一样,但是就是安装试用版 2.接受许可协议 ...

  10. java_I/O字符流

    I/O流(Stream) INPUT:输入流,从文件里读OUPUT:输出流,写内容到文件 IO流分为:字符流和字节流 字符流:处理纯文本文件. 字节流:处理可以所有文件. 字符输出流测试: @Test ...