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注入方式. 开源地址: ...
随机推荐
- python学习之掷骰子游戏
""" 通过学习的python知识,写一个简单的python小游戏 游戏名字:掷骰子比大小 游戏规则: 1.玩家可以选择玩掷几个骰子游戏(默认3个) 2.玩家可以设置双方 ...
- React/数据流
“Props” 当 React 元素为用户自定义组件时,它会将 JSX 所接收的属性(attributes)转换为单个对象传递给组件,这个对象被称之为 “props”. props的只读性 组件无论是 ...
- java轻松玩转httpget和httppost
废话不多少说,直接上代码 //get请求 public static void HttpClientGet(String url) throws Exception { // 获取http客户端 Cl ...
- 工作流引擎Activiti
背景: 在计算机尚未普及时,许多工作流程采用手工传递纸张表单的方式,一级一级审批签字, 工作效率非常低下,对于数据统计以及生成报表的功能,需要经过大量的手工操作才能实现. 随着电脑的普及,这些工作的参 ...
- sql 发生死锁
SELECT request_session_id spid , OBJECT_NAME(resource_associated_entity_id) tableName FROM sys.dm_tr ...
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP)
2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP) 链接:https://ac.nowcoder.com/acm/contest/163/ ...
- Java常用数学类和BigDecimal
笔记: Math类 * java.lang.Math提供了一系列静态方法用于科学计算:其方法的参数和返回值类型一般为double型. * abs 绝对值 * acos,asin,atan,cos,si ...
- 陈硕muduo
https://github.com/chenshuo/muduo muduo 阅读 https://www.cnblogs.com/qbits/p/11101678.html
- [ 转载 ] Java基础二
前言 关于赢在面试的Java题系列基本收集整理完成了,所有题目都是经过精心挑选的,很基础又考验求职者的基本功,应该说被面试到的几率很大.这里整理挑选出来供大家面试前拿来看一看,所有题目整理自网络,有一 ...
- Nginx中ngx_http_fastcgi_module
转发请求到 FastCGI 服务器器,不不⽀支持 php 模块⽅方式指令:15.1 fastcgi_pass设置 fastcgi 服务器器的地址.地址可以指定为域名或 IP 地址,以及端⼝口Synta ...