7 AOP
AOP:Aspect Oriented Programming 面向切面编程。AOP是对面向对象编程的一种补充,在运行时动态地将代码切入到类的指定方法、指定位置的编程思想。将不同的方法的同一位置抽象成一个切面对象,对该切面进行编程,就是AOP。
AOP更专业的说法:通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术, AOP是OOP的延续与补充。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高开发效率。
底层实现:
(1) JDK的动态代理:针对实现了接口的类产生代理;
(2) Cglib的动态代理:针对未是实现接口的类产生代理,应用的是底层字节码增强技术生成当前类的子类对象。
1 AOP 的优点
(1) 降低模块之间的耦合度
(2) 使系统更容易扩展
(3) 更好的代码复用
(4) 非业务代码更加集中,不分散,便于统一管理
(5) 业务代码更简洁纯粹,不掺杂其他代码影响
2 实例
2.1 动态代理实现AOP
Cal接口
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);
}
实现类
public class CalImpl implements Cal {
public int add(int num1, int num2) {
System.out.println("add方法的参数是["+num1+","+num2+"]");
int result = num1+num2;
System.out.println("add方法的结果是"+result);
return result;
}
public int sub(int num1, int num2) {
System.out.println("sub方法的参数是["+num1+","+num2+"]");
int result = num1-num2;
System.out.println("sub方法的结果是"+result);
return result;
}
public int mul(int num1, int num2) {
System.out.println("mul方法的参数是["+num1+","+num2+"]");
int result = num1*num2;
System.out.println("mul方法的结果是"+result);
return result;
}
public int div(int num1, int num2) {
System.out.println("div方法的参数是["+num1+","+num2+"]");
int result = num1/num2;
System.out.println("div方法的结果是"+result);
return result;
}
}
上述代码中日志信息和业务逻辑的耦合性很高,不利于系统的维护,使用AOP可以进行优化。
如何来实现AOP?使用动态代理的方式来实现。给业务代码找一个代理,打印日志信息的工作交个代理来做,这样的话业务代码就只需要关注自身的业务即可。
动态代理
public class MyInvocationHandler implements InvocationHandler {
/**
* 接受代理对象
*/
private Object object;
/**
* 返回代理对象
* @return
*/
public Object bind(Object object) {
this.object = object;
return Proxy.newProxyInstance(object.getClass().getClassLoader(), object.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName() + "方法的参数是:" + Arrays.toString(args));
Object result = method.invoke(object, args);
System.out.println(method.getName() + "方法的计算结果是:" + result);
return result;
}
}
测试
public class CalTest {
public static void main(String[] args) {
Cal cal = new CalImpl();
MyInvocationHandler handler = new MyInvocationHandler();
Cal cal1 = (Cal)handler.bind(cal);
cal1.add(4, 2);
cal1.sub(8, 2);
cal1.mul(16, 2);
cal1.div(32, 2);
}
}
2.2 Spring 实现AOP
切面
@Aspect
@Component
public class LoggerAspect { /**
* 前置通知
* @param joinPoint
*/
@Before("execution (public int com.latiny.aopa.impl.CalImpl.*(..))")
public void before(JoinPoint joinPoint) {
String name = joinPoint.getSignature().getName();
String args = Arrays.toString(joinPoint.getArgs());
System.out.println(name + "方法的参数为:" + args);
} /**
* 后置通知
* @param joinPoint
*/
@After("execution (public int com.latiny.aopa.impl.CalImpl.*(..))")
public void after(JoinPoint joinPoint) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法执行完毕。");
} @AfterReturning(value = "execution (public int com.latiny.aopa.impl.CalImpl.*(..))", returning = "result")
public void afterReturn(JoinPoint joinPoint, Object result) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法返回结果为:" + result);
} @AfterThrowing(value = "execution (public int com.latiny.aopa.impl.CalImpl.*(..))", throwing = "e")
public void afterThrowing(JoinPoint joinPoint, Exception e) {
String name = joinPoint.getSignature().getName();
System.out.println(name + "方法抛出的异常为:" + e);
}
}
被切的类需要加注解@Component
@Component
public class CalImpl implements Cal { @Override
public int add(int num1, int num2) {
int result = num1 + num2;
return result;
} @Override
public int sub(int num1, int num2) {
int result = num1 - num2;
return result;
} @Override
public int mul(int num1, int num2) {
int result = num1 * num2;
return result;
} @Override
public int div(int num1, int num2) {
int result = num1 / num2;
return result;
}
}
配置文件
<?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"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.3.xsd
">
<!-- 自动扫描-->
<context:component-scan base-package="com.latiny"></context:component-scan> <!--使Aspect注解自动生效,为目标类自动生成代理对象-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
context:component-scan:将com.latiny 包中的所有类进行扫描,如果该类同时
添加了@Component,则将该类扫描IOC容器中,交给IOC进行管理。
测试
public class CalTest2 {
public static void main(String[] args) {
// 加载配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
Cal cal1 = (Cal) context.getBean("calImpl");
cal1.add(4, 2);
cal1.sub(8, 2);
cal1.mul(16, 2);
cal1.div(32, 0);
}
}
AOP相关概念
(1) 切面:横切关注点被模块化的抽象对象;
(2) 通知:切面完成的工作;
(3) 目标:被通知的对象,即被横切的对象;
(4) 代理:切面、通知、目标混合之后的对象;
(5) 连接点:通知要插入业务代码的具体位置;
(6) 切入点:AOP通过切点定位到连接点;
7 AOP的更多相关文章
- 基于spring注解AOP的异常处理
一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...
- Spring基于AOP的事务管理
Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...
- 学习AOP之透过Spring的Ioc理解Advisor
花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...
- 学习AOP之深入一点Spring Aop
上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...
- 学习AOP之认识一下Spring AOP
心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- .NET里简易实现AOP
.NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...
- 在.Net中实现自己的简易AOP
RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...
- 使用Java原生代理实现AOP
### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...
- 【开源】.Net Aop(静态织入)框架 BSF.Aop
BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...
随机推荐
- vscode 基本知识以及如何配置 C++ 环境
参考: 在用VSCode? 看完这篇文章, 开发效率翻倍!最后一条厉害了~ Visual Studio Code(VS code)你们都在用吗?或许你们需要看一下这篇博文 按下 ctrl+K,再按下 ...
- java注解日志记录到数据库
1. pom添加依赖包 <!--添加aop依赖--><dependency> <groupId>org.springframework.boot</group ...
- ubuntu创建kvm虚拟机
CPU虚拟化支持 [root@ubuntu~]# egrep -o '(vmx|svm)' /proc/cpuinfo vmx vmx vmx vmx KVM环境 [root@ubuntu ~]# a ...
- springboot 部署到tomcat,获取根路径问题。空格变为%20
String path = ResourceUtils.getURL("classpath:").getPath()+"static/upload"; Syst ...
- 使用MySQL审计Plugin
本文来源:http://blog.chinaunix.net/uid-20785090-id-5018977.html 越来越多的企业把应用往mysql上迁移,这时候对数据库的审计又成了一件紧急的事情 ...
- Ubuntu 系统信息相关命令
系统信息相关命令 本节内容主要是为了方便通过远程终端维护服务器时,查看服务器上当前 系统日期和时间 / 磁盘空间占用情况 / 程序执行情况 本小结学习的终端命令基本都是查询命令,通过这些命令对系统资源 ...
- Ubuntu安装cmake 3.9
wget https://cmake.org/files/v3.9/cmake-3.9.2.tar.gz # 下载 cd cmake-3.9.2 ./configure sudo make & ...
- IIS 自动化发布工具实现-Manager【二】
思路: 1.首先是要获取项目的差异文件列表,实现方式是通过cmd 执行git 命令. git pull 拉取最新代码 git log 查看git签入记录 ,使用参数 --pretty=for ...
- jade总结
随着时间的迁移,要跟官方api相匹配 jade的缺点 1.可移植性差 2.调试困难 3.性能不是非常出色(不是为性能设计,可以使用dot, http://olado.github.io/) 选择的 ...
- linux(3)
一.用户和组的管理 Linux/Unix是多用户系统: root是超级用户,拥有最高权限.其它用户及权限由root来管理.对比Windows系统: 控制面板 -> 管理工具 -> 计算机管 ...