Spring框架——AOP
Spring AOP 面向切面编程,OOP面向对象编程,将程序中所有参与模块都抽象成对象,然后通过对象之间的相互调用完成需求。
AOP是OOP的一种补充,是在另外一个维度上抽象出对象,具体是指程序运行时动态地将非业务代码切入到业务代码中,从而实现代码的解耦合,将非业务代码抽象成一个对象,对该对象进行编程就是面向切面编程思想。
AOP的优点:
1、大大降低模块之间的耦合性;
2、提高代码的维护性;
3、提高代码的复用性;
4、集中管理非业务代码,便于维护;
5、业务代码不受非业务代码的影响,逻辑更加清晰;
JDK代理方式
委托类
package com.sunjian.aop;
/**
* @author sunjian
* @date 2020/3/16 8:12
*/
public interface Cal {
public int add(int num1, int num2);
public int sub(int num1, int num2);
public int mul(int num1, int num2);
public int div(int num1, int num2);
}
package com.sunjian.aop;
/**
* @author sunjian
* @date 2020/3/16 8:13
*/
public class MyCal implements Cal {
public int add(int num1, int num2) {
int result = num1 + num2;
return result;
}
public int sub(int num1, int num2) {
int result = num1 - num2;
return result;
}
public int mul(int num1, int num2) {
int result = num1 * num2;
return result;
}
public int div(int num1, int num2) {
int result = num1 / num2;
return result;
}
}
代理类
package com.sunjian.aop;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
/**
* @author sunjian
* @date 2020/3/16 8:14
*/
public class MyInvocationHandler implements InvocationHandler {
private Object object = null; // 委托对象
// 返回代理对象
public Object bind(Object object){
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "的参数是 " + Arrays.toString(args));
Object result = method.invoke(this.object, args);
System.out.print(method.getName() + "的结果是 ");
return result;
}
}
测试类
package com.sunjian.aop;
/**
* @author sunjian
* @date 2020/3/16 8:19
*/
public class Test {
public static void main(String[] args) {
Cal cal = new MyCal();
MyInvocationHandler myInvocationHandler = new MyInvocationHandler();
Cal proxy = (Cal) myInvocationHandler.bind(cal);
System.out.println(proxy.add(10,3));
System.out.println(proxy.sub(10,3));
System.out.println(proxy.mul(10,3));
System.out.println(proxy.div(10,3));
}
}
打印结果
add的参数是 [10, 3] add的结果是 13 sub的参数是 [10, 3] sub的结果是 7 mul的参数是 [10, 3] mul的结果是 30 div的参数是 [10, 3] div的结果是 3
Spring 方式
AOP 核心概念
1、切面对象,根据切面抽象出来的对象,在实现类 MyCal 的所有方法中加入日志部分,抽象成一个切面对象LoggerAspect;
2、通知,切面对象的具体代码,即非业务代码,loggerAspect打印日志的各种操作;
3、目标,被切割的对象,MyCal;
4、代理,切面对象,通知,目标混合之后的产物,Spring通过JDK动态代理创建,真正执行代码的对象;
5、连接点,需要被横切的位置,即通知要插入业务代码的具体位置;
委托类
package com.sunjian.aop;
/**
* @author sunjian
* @date 2020/3/16 8:12
*/
public interface Cal {
public int add(int num1, int num2);
public int sub(int num1, int num2);
public int mul(int num1, int num2);
public int div(int num1, int num2);
}
package com.sunjian.aop;
import org.springframework.stereotype.Component;
/**
* @author sunjian
* @date 2020/3/16 8:13
*/
@Component("myCal")
public class MyCal implements Cal {
public int add(int num1, int num2) {
int result = num1 + num2;
return result;
}
public int sub(int num1, int num2) {
int result = num1 - num2;
return result;
}
public int mul(int num1, int num2) {
int result = num1 * num2;
return result;
}
public int div(int num1, int num2) {
int result = num1 / num2;
return result;
}
}
代理类
package com.sunjian.aop;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import java.util.Arrays;
/**
* @author sunjian
* @date 2020/3/16 9:20
*/
@Aspect
@Component
public class LoggerAspect {
@Before(value = "execution(public int com.sunjian.aop.MyCal.*(..))")
public void before(JoinPoint joinPoint) {
// 获取方法名
String name = joinPoint.getSignature().getName();
// 参数列表
String args = Arrays.toString(joinPoint.getArgs());
System.out.println(name + "的参数是 " + args);
}
@AfterReturning(value = "execution(public int com.sunjian.aop.MyCal.*(..))", returning = "result")
public void after(JoinPoint joinPoint, Object result) {
System.out.println(joinPoint.getSignature().getName() + "方法的执行结果是 " + result);
}
@After(value = "execution(public int com.sunjian.aop.MyCal.*(..))")
public void after(JoinPoint joinPoint){
System.out.println(joinPoint.getSignature().getName() + "业务执行完毕...");
}
@AfterThrowing(value = "execution(public int com.sunjian.aop.MyCal.*(..))", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e){
System.out.println(joinPoint.getSignature().getName() + "方法抛出异常 " + e);
}
}
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"
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/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 自动扫描 -->
<context:component-scan base-package="com.sunjian"></context:component-scan>
<!-- 为目标类自动生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
将⽬标类和切⾯类交给 IoC 容器管理, IoC 容器会自动创建实例化对象,结合 JDK 动态代理,自动实现 InvocationHandler 接口,整合完成业务代码和非业务代码的解耦合。
context:component-scan 将 com.sunjian 包中的所有类扫描到 IoC 容器中,需要结合 @Component 注解完成。
aop:aspectj-autoproxy Spring 会结合切面类和目标类自动生成动态代理对象,代理对象完成非业务代码(日志打印)。
测试类
package com.sunjian.aop;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @author sunjian
* @date 2020/3/16 8:19
*/
public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("aop.xml");
Cal cal = (Cal) applicationContext.getBean("myCal");
System.out.println(cal.add(10,3));
System.out.println(cal.sub(10,3));
System.out.println(cal.mul(10,3));
System.out.println(cal.div(10,3));
}
}
打印结果
add的参数是 [10, 3] add业务执行完毕... add方法的执行结果是 13 13 sub的参数是 [10, 3] sub业务执行完毕... sub方法的执行结果是 7 7 mul的参数是 [10, 3] mul业务执行完毕... mul方法的执行结果是 30 30 div的参数是 [10, 3] div业务执行完毕... div方法的执行结果是 3 3
另:同时给一个目标添加多个切面时的执行顺序,实现 org.springframework.Ordered 接口, ordered 越⼩最先执⾏。
Spring框架——AOP的更多相关文章
- spring框架 AOP核心详解
AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...
- 跟着刚哥学习Spring框架--AOP(五)
AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...
- spring框架aop用注解形式注入Aspect切面无效的问题解决
由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...
- Spring框架——AOP代理
我们知道AOP代理指的就是设计模式中的代理模式.一种是静态代理,高效,但是代码量偏大:另一种就是动态代理,动态代理又分为SDK下的动态代理,还有CGLIB的动态代理.Spring AOP说是实现了AO ...
- Spring框架-AOP详细学习[转载]
参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...
- Spring框架 AOP面向切面编程(转)
一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...
- 10 Spring框架 AOP (三) Spring对AspectJ的整合
上两节我们讲了Spring对AOP的实现,但是在我们的开发中我们不太使用Spring自身的对AOP的实现,而是使用AspectJ,AspectJ是一个面向切面的框架,它扩展了Java语言.Aspect ...
- Spring框架AOP学习总结(下)
目录 1. AOP 的概述 2. Spring 基于AspectJ 进行 AOP 的开发入门(XML 的方式): 3.Spring 基于AspectJ 进行 AOP 的开发入门(注解的方式): 4.S ...
- 08 Spring框架 AOP (一)
首先我们先来介绍一下AOP: AOP(Aspect Orient Programming),面向切面编程,是面向对象编程OOP的一种补充.面向对象编程是从静态角度考虑程序的结构,面向切面编程是从动态的 ...
- 09 Spring框架 AOP (二) 高级用法
上一篇文章我们主要讲了一点关于AOP编程,它的动态考虑程序的运行过程,和Spring中AOP的应用,前置通知,后置通知,环绕通知和异常通知,这些都是Spring中AOP最简单的用法,也是最常用的东西, ...
随机推荐
- 转:zabbix 2.0.6监控cisco交换机 2950 2960s 3560G
转自: http://blog.chinaunix.net/uid-24250828-id-3806551.html 想在zabbix 上监控交换机端口的流量,找了两天的模板,包括官方的和网友写的.在 ...
- 跟随大神实现简单的Vue框架
自己用vue也不久了,学习之初就看过vue实现的原理,当时看也是迷迷糊糊,能说出来最基本的,但是感觉还是理解的不深入,最近找到了之前收藏的文章,跟着大神一步步敲了一下简易的实现,算是又加深了理解. 原 ...
- java集合 list与Set、Map区别
1.List,Set都是继承自Collection接口,Map则不是. 2.List特点:元素有放入顺序,元素可重复 ,Set特点:元素无放入顺序,元素不可重复,重复元素会覆盖掉 ,(注意:元素虽 ...
- <USACO09FEB>庙会捷运Fair Shuttleの思路
一个没有被我成功证明的 贪心 但是 ac了的 别人排序都是排终点.但我的排终点错了emm排起点才对qvq 有没有人友情看看怎么证(没有 #include<cstdio> #include& ...
- 每天一个linux命令(15)-tail
tail 命令从指定点开始将文件写到标准输出.使用tail命令的-f选项可以方便的查阅正在改变的日志文件,tail -f filename会把filename里最尾部的内容显示在屏幕上,并且不断刷新, ...
- 手写实现vue的MVVM响应式原理
文中应用到的数据名词: MVVM ------------------ 视图-----模型----视图模型 三者与 Vue 的对应:view 对应 te ...
- JavaScript中点击按钮弹出新的浏览器窗口
*/ * Copyright (c) 2016,烟台大学计算机与控制工程学院 * All rights reserved. * 文件名:text.js * 作者:常轩 * 微信公众号:Worldhel ...
- Python神经网络编程笔记
神经元 想一想便知道,当一个人捏你一下以至于你会痛得叫起来的力度便是神经元的阈值,而我们构建的时候也是把这种现象抽象成一个函数,叫作激活函数. 而这里便是我们使用sigmoid函数的原因,它是一个很简 ...
- JZOJ 5257. 小X的佛光 (Standard IO)
5257. 小X的佛光 (Standard IO) Time Limits: 2000 ms Memory Limits: 524288 KB Description Input Output Sam ...
- Ubuntu中VMware tools的安装步骤
按照下面的步骤,轻松解决!! 1.点击导航栏中的虚拟机,下面的安装VMware tools 2.点击桌面上的光盘,进入后,将tar.gz文件复制到桌面,然后右击提取到此处: 3.在桌面打开终端,cd到 ...