AOP编程

​ AOP为Aspect Oriented Programming的缩写,意为:面向切面编程。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

​ 学习AOP之后,可以在不修改源码的情况下,进行源码的增强业务,进行权限的校验,日志记录,性能监控,事务控制等。

Spring底层的AOP原理

  • 动态代理(静态代理)

    • JDK动态代理: 面向接口的,只能对实现了接口的类产生代理
    • Cglib动态代理(类似于JavaSsit第三方代理技术):对没有实现接口的类产生代理对象(生成子类对象)
  • 类实现了接口,Spring就用JDK动态代理,没有实现接口的,用Cglib动态代理,Spring底层可以自动切换

Spring的AOP开发入门(1)(基于XML开发)

1. 引入基本开发包和AOP开发相关的包

第一个aop联盟

第二个aspectj的依赖

第三个AOP核心包

第四个Spring与aspects整合的包

2. 引入xml配置约束文件

写切面的约束:aspect.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">
<!--切面编程配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="p1" expression="execution(* com.yd.service.impl.UserServiceImpl.add(..))"/>
<!--配置切面类-->
<aop:aspect ref="myAspect">
<aop:before method="log" pointcut-ref="p1"></aop:before>
</aop:aspect>
</aop:config>
</beans>

写spring扫描类文件,管理相关类的对象:spring.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" 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"> <!-- bean definitions here --> <context:component-scan base-package="com.yd.service"></context:component-scan>
<context:component-scan base-package="com.yd.aspect"></context:component-scan> </beans>

3. 编写原本的代码(切入点)

UserService:

public interface UserService {
//添加用户方法
public void add();
}

接口的实现类UserServiceImpl:

  • 使用@Service将该类交由spring容器管理
@Service
public class UserServiceImpl implements UserService { @Override
public void add(){
System.out.println("添加用户信息...");
}
}

4. 编写增强类(通知)

  • 使用@Component将该类交由spring容器管理
@Component
public class MyAspect {
public void log(){
System.out.println("添加日志");
}
}

5. 运行测试代码

public class Demo {

    @Test
public void run(){
//引入配置文件
ApplicationContext ac = new ClassPathXmlApplicationContext( "spring.xml","aspect.xml");
//从spring容器中获取对象
UserService userService = (UserService)ac.getBean("userServiceImpl");
//执行对象方法
userService.add();
} }

运行结果:

Spring的AOP开发入门(2)(基于XML开发)

UserService:

public interface UserService {
public void add();
public void delete();
public String deleteReturn();
public void deleteAround();
public void update(String uname,int pwd);
public String updateReturn(String uname,int pwd);
public void selectException();
public void selectFin();
}

实现类UserServiceImpl:

@Service
public class UserServiceImpl implements UserService { @Override
public void add(){
System.out.println("添加用户信息...");
} @Override
public void delete() {
System.out.println("删除用户信息...");
}
@Override
public String deleteReturn() {
System.out.println("删除用户,有返回值...");
return "123";
}
@Override
public void deleteAround(){
System.out.println("删除信息deleteAround...");
} @Override
public void update(String uname,int pwd) {
System.out.println("uname:"+uname+" pwd:"+pwd);
} @Override
public String updateReturn(String uname,int pwd) {
System.out.println("uname:"+uname+" pwd:"+pwd);
return uname;
} @Override
public void selectException() {
System.out.println("select异常。。。");
System.out.println(1/0);
System.out.println("select2。。。");
} @Override
public void selectFin() {
System.out.println("select无异常。。。"); } }

增强类MyAspect:

@Component
public class MyAspect { public void check(){
System.out.println("----之前校验身份");
} public void back(){
System.out.println("----之后增强");
} /**
* 接收原方法返回值的后置增强方法
* @param obj 切入点的返回值
*/
public void backReturn(Object obj){
System.out.println("后置接收切入点返回值:"+obj);
} /**
* 环绕增强
* @param point 连接点
* @throws Throwable
*/
public void around(ProceedingJoinPoint point) throws Throwable {
System.out.println("----之前增强");
//执行切入点的方法
point.proceed();
System.out.println("----之后增强");
} /**
* 环绕增强,接收切入点的传入的参数
* @param point
* @throws Throwable
*/
public void aroundParam(ProceedingJoinPoint point)throws Throwable{
System.out.println("---之前增强");
//获取切入点的参数
Object[] args = point.getArgs();
point.proceed();
System.out.println("---之后增强 切入点参数1:"+args[0]+" 参数2:"+args[1]);
}
/**
* 环绕增强,接收切入点的传入的参数,切接收返回
* @param point
* @throws Throwable
*/
public void aroundReturn(ProceedingJoinPoint point)throws Throwable{
System.out.println("---之前增强");
//获取切入点的参数
Object[] args = point.getArgs();
String str = (String)point.proceed();
System.out.println("---之后增强 切入点参数1:"+args[0]+" 参数2:"+args[1]+" 返回值:"+str);
} /**
* 切入点有异常
* @param e 异常
*/
public void afterCatch(Exception e){
System.out.println(e.getMessage());
System.out.println("---捕获异常");
} public void finallyDo(){
System.out.println("finally,总会执行...");
}
}

AOP配置文件:

<?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">
<!--切面编程配置-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="p1" expression="execution(* com.yd.service.impl.UserServiceImpl.add(..))"/>
<aop:pointcut id="p2" expression="execution(* com.yd.service.impl.UserServiceImpl.delete(..))"/>
<aop:pointcut id="p3" expression="execution(* com.yd.service.impl.UserServiceImpl.deleteReturn(..))"/>
<aop:pointcut id="p4" expression="execution(* com.yd.service.impl.UserServiceImpl.deleteAround(..))"/>
<aop:pointcut id="p5" expression="execution(* com.yd.service.impl.UserServiceImpl.update(..))"/>
<aop:pointcut id="p6" expression="execution(* com.yd.service.impl.UserServiceImpl.updateReturn(..))"/>
<aop:pointcut id="p7" expression="execution(* com.yd.service.impl.UserServiceImpl.selectException(..))"/>
<aop:pointcut id="p8" expression="execution(* com.yd.service.impl.UserServiceImpl.selectFin(..))"/> <!--配置切面类-->
<aop:aspect ref="myAspect">
<!-- 之前增强-->
<aop:before method="check" pointcut-ref="p1"></aop:before>
<!-- 之后增强-->
<aop:after-returning method="back" pointcut-ref="p2"></aop:after-returning>
<!-- 之后增强接收切入点返回值 obj:增强方法接收返回值的参数,必须与方法中参数名一致-->
<aop:after-returning method="backReturn" pointcut-ref="p3" returning="obj"></aop:after-returning>
<!-- 环绕增强-->
<aop:around method="around" pointcut-ref="p4"></aop:around>
<!-- 环绕增强,获取切入点传入的参数信息-->
<aop:around method="aroundParam" pointcut-ref="p5"></aop:around>
<!-- 环绕增强,获取切入点传入的参数信息,且有返回-->
<aop:around method="aroundReturn" pointcut-ref="p6"></aop:around> <!-- 最终通知,有无异常都会执行,相当于finally-->
<aop:after method="finallyDo" pointcut-ref="p7"></aop:after> <!-- 切入点有异常,后置增强捕获 throwing="e"异常参数,必须与方法中一致-->
<aop:after-throwing method="afterCatch" pointcut-ref="p7" throwing="e"></aop:after-throwing> <aop:after method="finallyDo" pointcut-ref="p8"></aop:after>
</aop:aspect>
</aop:config>
</beans>

测试类:

public class Demo {

    @Test
public void run(){
ApplicationContext ac = new ClassPathXmlApplicationContext( "spring.xml","aspect.xml");
UserService userService = (UserService)ac.getBean("userServiceImpl");
//userService.add();
//userService.delete();
//userService.deleteReturn();
//userService.deleteAround();
//userService.update("张三",1234);
//userService.updateReturn("李四",121);
//userService.selectException();
userService.selectFin();
}
  • 注意:最终通知after和后置异常通知after-throwing的顺序不同,打印结果顺序不同

方式一:

运行结果

方式二:

运行结果:

切入点表达式语法

基于execution的函数完成的

语法

  • execution([访问修饰符] 方法返回值 包名.类名.方法名(参数))

com.spring.service.UserServiceImpl.add(..) 一般情况最好将方法名写完整

com.spring.service.UserServiceImpl.*(..) 开发中用的最多的是这种,对当前类下所有的方法做增强处理(场景:事务处理)

com.spring.service.impl.save(..)

com.spring.service.impl.*(..) 表示: com.spring.service.impl类下所有方法被增强

* *.*service.impl.add(..)没有包可以用*代替

* com.spring..(..)表示com.spring包下所有的类,所有方法都被增强

04-Spring中的AOP编程之基于xml开发的更多相关文章

  1. Spring中Bean的配置:基于XML文件的方式

    Bean的配置一共有两种方式:一种是基于XML文件的方式,另一种是基于注解的方式.本文主要介绍基于XML文件的方式 <bean id="helloWorld" class=& ...

  2. Spring中的AOP注解方式和XML方式

    应掌握内容:1. AOP的全名2. AOP的实现原理[静态代理和动态代理]3. 注解方式的配置4. 通知类型     A. 每种通知的特点和使用方式    B. 获取各种数据,方便日后操作5. 执行表 ...

  3. Spring AOP——Spring 中面向切面编程

    前面两篇文章记录了 Spring IOC 的相关知识,本文记录 Spring 中的另一特性 AOP 相关知识. 部分参考资料: <Spring实战(第4版)> <轻量级 JavaEE ...

  4. Spring中的AOP 专题

    Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...

  5. Spring入门3.AOP编程

    Spring入门3.AOP编程 代码下载: 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa 前言: 前面学习的知识是Spring在Java项目中的IoC或DJ,这 ...

  6. JavaWeb_(Spring框架)认识Spring中的aop

    1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...

  7. (五)Spring 中的 aop

    目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...

  8. Spring中的AOP

    什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...

  9. Spring中关于AOP的实践之概念

    一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...

  10. Spring学习笔记(四)—— Spring中的AOP

    一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...

随机推荐

  1. (读书笔记)基于CMMI的软件工程及实训指导------第一章软件工程基础

    第一章------软件工程基础 1.软件工程基本原理 (1)按照软件生命周期的阶段划分制订计划,严格依据计划进行管理 (2)坚持进行阶段评审 (3)实行严格的产品控制 (4)采用现代程序设计技术 (5 ...

  2. Nginx+UWSGI+supervisor

    Tengine是由淘宝网发起的Web服务器项目.它在Nginx的基础上,针对大访问量网站的需求,添加了很多高级功能和特性.Tengine的性能和稳定性已经在大型的网站如淘宝网,天猫商城等得到了很好的检 ...

  3. 启动JAVA服务

    # -*- coding: utf-8 -*- import re import sys from subprocess import Popen, PIPE import os import tim ...

  4. redis之redisObject对象

    redisObject对象 无论什么数据类型,redis都是以key-value形式保存,并且所有的key都是字符串redis每存储一条数据,都会生成一个redisObject对象,通过redisOb ...

  5. 在Windows系统上安装和配置Jenkins自动发布

    一.安装jenkins的流程转载于: https://www.jianshu.com/p/de9c4f5ae7fa 二.在window中执行批处理文件bat或者powershell可以成功,但是Jen ...

  6. js判断变量数据类型typeof、instanceof、Object.prototype.toString.call()、 constructor

    JavaScript有4种方法判断变量的类型,分别是typeof.instanceof.Object.prototype.toString.call()(对象原型链判断方法). constructor ...

  7. oracle建表和sqlserver建表

    oracle declare num number;begin select count(1) into num from user_all_tables where Upper(Table_Name ...

  8. phpmyadmin scripts/setup.php 反序列化漏洞(WooYun-2016-199433)(Kali)

    ​ phpmyadmin 2.x版本中存在一处反序列化漏洞,通过该漏洞,攻击者可以读取任意文件或执行任意代码. 通过vulhub靶场进行复现操作 1.首先搭建靶场环境(采用Kali) cd vulhu ...

  9. 【NumPy】Python将数组中低于一定百分比的值替换

    情景举例 现有一个一维数组(或二维进行遍历)存放着很多,找到低于中位数20%的值并将小于该值的数全部替换为该值. 涉及方法 np.median(data, axis=0)用于计算数组中元素的中位数(中 ...

  10. elementUI el-tree报错 Cannot read property ‘setCheckedKeys’ of undefined"

    给树节点赋值时,执行下面代码会报错,原因是:DOM元素未加载完成. 以下为错误写法. handleRowClick(row) { this.$refs.tree.setCheckedKeys(ids) ...