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的更多相关文章

  1. 基于spring注解AOP的异常处理

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...fin ...

  2. Spring基于AOP的事务管理

                                  Spring基于AOP的事务管理 事务 事务是一系列动作,这一系列动作综合在一起组成一个完整的工作单元,如果有任何一个动作执行失败,那么事务 ...

  3. 学习AOP之透过Spring的Ioc理解Advisor

    花了几天时间来学习Spring,突然明白一个问题,就是看书不能让人理解Spring,一方面要结合使用场景,另一方面要阅读源代码,这种方式理解起来事半功倍.那看书有什么用呢?主要还是扩展视野,毕竟书是别 ...

  4. 学习AOP之深入一点Spring Aop

    上一篇<学习AOP之认识一下SpringAOP>中大体的了解了代理.动态代理及SpringAop的知识.因为写的篇幅长了点所以还是再写一篇吧.接下来开始深入一点Spring aop的一些实 ...

  5. 学习AOP之认识一下Spring AOP

    心碎之事 要说知道AOP这个词倒是很久很久以前了,但是直到今天我也不敢说非常的理解它,其中的各种概念即抽象又太拗口. 在几次面试中都被问及AOP,但是真的没有答上来,或者都在面上,这给面试官的感觉就是 ...

  6. .Net中的AOP系列之构建一个汽车租赁应用

    返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...

  7. .NET里简易实现AOP

    .NET里简易实现AOP 前言 在MVC的过滤器章节中对于过滤器的使用就是AOP的一个实现了吧,时常在工作学习中遇到AOP对于它的运用可以说是很熟练了,就是没想过如果自己来实现的话是怎么实现的,性子比 ...

  8. 在.Net中实现自己的简易AOP

    RealProxy基本代理类 RealProxy类提供代理的基本功能.这个类中有一个GetTransparentProxy方法,此方法返回当前代理实例的透明代理.这是我们AOP实现的主要依赖. 新建一 ...

  9. 使用Java原生代理实现AOP

    ### 本文由博主柒.原创,转载请注明出处 ### 完整源码下载地址 [https://github.com/MatrixSeven/JavaAOP](https://github.com/Matri ...

  10. 【开源】.Net Aop(静态织入)框架 BSF.Aop

    BSF.Aop .Net 免费开源,静态Aop织入(直接修改IL中间语言)框架,类似PostSharp(收费): 实现前后Aop切面和INotifyPropertyChanged注入方式. 开源地址: ...

随机推荐

  1. Vue路由相关配置

    什么是路由? 1.在以前页面跳转使用的是超链接a标签或者js location.href,而路由是跳转切换组件的跳转方式 2.路由就是监听url的改变并提供相对应的组件用于展示 3.vue-route ...

  2. navicat远程连接mysql错误

    确保端口与服务正常. 如果都正常,那么服务有可能没有添加远程访问. 本人链接报错10060,那么问题出在阿里云的主机默认不开放3306端口,那么在安全组策略中加入对应的端口   登录后输入 use m ...

  3. 深入理解Kubernetes资源限制:内存

    写在前面 当我开始大范围使用Kubernetes的时候,我开始考虑一个我做实验时没有遇到的问题:当集群里的节点没有足够资源的时候,Pod会卡在Pending状态.你是没有办法给节点增加CPU或者内存的 ...

  4. python c++ 混合编程中python调用c++string返回类型的函数,python中返回为数字的解决办法

    本随笔解决 Python使用ctypes 调用c++dll 字符串返回类型函数,在python中显示为数字:原文解决方案见so: https://stackoverflow.com/questions ...

  5. 【1 封新邀请】想跟谷歌、七牛、kyligence 等大佬面对面的交流吗?

    2020 年 1 月 4 日 - 5 日,"ECUG Con 2020"大会将于杭州举行.本次大会以"ECUG For Future"为主题,围绕五大技术主题, ...

  6. [2019年湘潭大学程序设计竞赛(重现赛)H chat][背包dp]

    链接:https://ac.nowcoder.com/acm/contest/893/H来源:牛客网 题目描述 在Casya生活的世界里,一天由m个小时组成. 最近Casya的女神终于答应在接下来的n ...

  7. Educational Codeforces Round 74 (Rated for Div. 2) A. Prime Subtraction

    链接: https://codeforces.com/contest/1238/problem/A 题意: You are given two integers x and y (it is guar ...

  8. [Google Guava] 2.1-不可变集合

    范例 01 public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of( 02 "red&quo ...

  9. tarjan等

    有向图注意v在栈中时,才用dfn更新low.无向图不用判断这个. SCC和边双,都是在返回时判断low==dfn. 点双就是找割点,low(v)>=dfn(u)时,把tarjan(v)过程中放入 ...

  10. PHP mysqli_close() 函数

    关闭先前打开的数据库连接: <?php $con=mysqli_connect("localhost","my_user","my_passwo ...