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. C++标准库里自带的数值类型和字符串互相转换函数

    需要包含头文件 #include <string> 数值类型转成string类型: string to_string(int val); string to_string(unsigned ...

  2. 表格中的DOM

    通过DOM来操作table跟在html中操作table是不一样的,下面来看看怎样通过DOM来操作table. 按照table的分布来创建: <table> <thead> &l ...

  3. 2019 GIAC-全球互联网架构大会课件

    百度云:https://pan.baidu.com/s/1Lt40UTP3hCIVS7LhPl2bKw密码:ovrh

  4. 【Day4】4.Request对象之Get请求与URL编码

    import urllib.parse as up import urllib.request as ur kw = '动漫' data ={ 'kw':kw, 'ie':'utf-8', 'pn': ...

  5. ln -s vs mount --bind

    First ,Symlinks and bind mounts are a whole different ballgame. ln -s you create a symbolic link,whi ...

  6. Install RabbitMQ on CentOS 7

    NOTE: this article is only for CentOS 7 How to Install RabbitMQ on CentOS 7 yum update Install erlan ...

  7. Linux教程 Find命令的使用

    Linux中的Find(查找)命令是在Linux系统中最重要并且更有用的命令之一.Find命令主要用于指定匹配文件条件的参数查找或者定位文件和目录的列表.Find命令能够被使用基于各种各样的条件,例如 ...

  8. opencv+python 添加文字 cv2.putText

    import cv2 img = cv2.imread('E:\\usb_test\\example\\yolov3\\rknn_emotion\\test_images\\llj5.jpg') fo ...

  9. BCB 编写服务程序的一个注意事项

      BCB编写服务,install报错的一个问题 今天编写了一个服务,最后INSTALL 的时候报错,如图: 经过近1小时的比较(俺过去写例子),居然无意中设置了一个属性               ...

  10. ZZNUOJ-2155-单身man集合-【标程做法:数位DP-1-10^8,提前暴力打表法: 砍时间复杂度到10^5】

    ZZNUOJ-2155: 单身MAN集合 题目描述: 单身man们突然集结起来了,虽然我们不知道它们想要干什么.你作为单身man的首领需要管理好每一只单身man,机智的你给每一只单身man编了一个编号 ...