04-Spring中的AOP编程之基于xml开发
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开发的更多相关文章
- Spring中Bean的配置:基于XML文件的方式
Bean的配置一共有两种方式:一种是基于XML文件的方式,另一种是基于注解的方式.本文主要介绍基于XML文件的方式 <bean id="helloWorld" class=& ...
- Spring中的AOP注解方式和XML方式
应掌握内容:1. AOP的全名2. AOP的实现原理[静态代理和动态代理]3. 注解方式的配置4. 通知类型 A. 每种通知的特点和使用方式 B. 获取各种数据,方便日后操作5. 执行表 ...
- Spring AOP——Spring 中面向切面编程
前面两篇文章记录了 Spring IOC 的相关知识,本文记录 Spring 中的另一特性 AOP 相关知识. 部分参考资料: <Spring实战(第4版)> <轻量级 JavaEE ...
- Spring中的AOP 专题
Caused by: java.lang.IllegalArgumentException: ProceedingJoinPoint is only supported for around advi ...
- Spring入门3.AOP编程
Spring入门3.AOP编程 代码下载: 链接: http://pan.baidu.com/s/11mYEO 密码: x7wa 前言: 前面学习的知识是Spring在Java项目中的IoC或DJ,这 ...
- JavaWeb_(Spring框架)认识Spring中的aop
1.aop思想介绍(面向切面编程):将纵向重复代码,横向抽取解决,简称:横切 2.Spring中的aop:无需我们自己写动态代理的代码,spring可以将容器中管理对象生成动态代理对象,前提是我们对他 ...
- (五)Spring 中的 aop
目录 文章目录 AOP概念 AOP原理 AOP术语 **`Spring`** 中的 **`aop`** 的操作 使用 `AspectJ` 实现 `aop` 的两种方式 AOP概念 浅理解 aop :面 ...
- Spring中的AOP
什么是AOP? (以下内容来自百度百科) 面向切面编程(也叫面向方面编程):Aspect Oriented Programming(AOP),通过预编译方式和运行期动态代理实现程序功能的统一维护的一种 ...
- Spring中关于AOP的实践之概念
一.什么是AOP AOP:也称作面向切面编程 在分享几个概念执行我想先举个栗子(可能例子举得并不是特别恰当): 1.假如路人A走在大街上,被一群坏人绑架了: 2.警察叔叔接到报警迅速展开行动:收集情报 ...
- Spring学习笔记(四)—— Spring中的AOP
一.AOP概述 AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.O ...
随机推荐
- lua中self的意义
原文链接 最近在用合宙的Air302开发物联网项目,因为合宙用的自家的luatOS操作系统,二次开发全都要用lua写,据说lua写起代码比C更方便,但是不会就是不会啊喂!!学不会就是不方便啊,例如这个 ...
- MySQL经典45题
一.数据库字段说明 1.学生表 Student(SId,Sname,Sage,Ssex)SId :学生编号Sname:学生姓名Sage :出生年月Ssex:学生性别 2.课程表 Course(CId, ...
- JS缓存三种方法_sessionStorage_localStorage_Cookie
1.sessionStorage:临时的会话存储 只要当前的会话窗口未关闭,存储的信息就不会丢失,即便刷新了页面,或者在编辑器中更改了代码,存储的会话信息也不会丢失. 2.localStorage:永 ...
- win10下 pytorch 跑模型 gpu利用率低
查阅资料后发现 Dataloader中的num_workers参数(线程数)设置为0,该为4后,nvidia-smi查看GPU占用率变为高(不要用任务管理器查看)
- jmeter在Linux上的安装及压力机配置
1.jmeter安装 (1)与控制机相同版本的java环境.安装包及插件: (2)关闭控制机上的防火墙: (3)保证机器在同一个局域网中(能ping通): (4)解压安装包,设置JMETER_HOME ...
- SQL注入绕过某waf的详细过程。
0x00起因 看到大家都有绕waf的payload,想了想,这样下去不行啊.总不能找人家要吧,于是我开启了电脑,开始我的bypass之路. 0x01过程 准备完毕后,开始,首先判断注入and 1=1 ...
- 5、MySQL中的锁
1.6. MySQL中的锁 InnoDB中锁非常多,总的来说,可以如下分类: 这些锁都是做什么的?具体含义是什么?我们现在来一一学习. 1.6.1.解决并发事务问题 我们已经知道事务并发执行时可能带来 ...
- mysql 的小问题
首先按下win+R 执行 services.msc 进入服务,查找到MySQL,点击停止服务,然后在控制台cmd进入本地的MySQL文件夹,我的文件名是mysql-8.0.26-winx64,进入后执 ...
- Debug --> python中的True False 0 1
今天看了下python中的一些基础知识,以offer64为例叭! 求 1+2+...+n ,要求不能使用乘除法.for.while.if.else.switch.case等关键字及条件判断语句(A?B ...
- js中函数(方法)注释
原文链接:https://blog.csdn.net/tianxintiandisheng/article/details/103764074 实例 /** * @function 处理表格的行 * ...