2:Spring AOP

AOP (Aspect Oriented Programming) 面向切面编程

OOP(Object Oriented Programming)面向对象编程,用对象的思想来完善程序

AOP是的OOP的一个补充,是在另外一个维度上抽象出的对象。

具体是指程序运行时动态的将非业务代码切入到业务代码中,从而实现程序的解耦合,将非业务抽象成一个对象,对对象编程就是面向对象编程。

在同样的地方有相同的方法抽象成一个切面----代码A切面对象。

AOP的优点:

  • 可以降低模块之间的耦合性
  • 提高代码的复用性
  • 集中管理代码的维护性
  • 集中管理代码的非义务代码,便于维护
  • 业务代码不受非业务代码的影响,逻辑更加清晰

    理解AOP

    1. 创建接口的计算器类

      package com.southwind.aop;

      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);
      }

2.实现类:

package com.southwind.aop.impl;

import com.southwind.aop.Cal;

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;
}
}

3.日志打印:

  • 在每个方法开始的位置输出参数的信息
  • 在每个方法的结束的位置输出结果信息

    对于计算器而言,加减乘除是业务代码,日志是非业务代码。

    AOP如何实现?:

    使用动态代理

    代理首先具备CaLImpl的基础功能,然后在这个基础上扩展日志功能

    1. 删除CalImpl方法中的打印日志的代码,只保留业务代码
    2. 创建MyinvocationHandler类,实现IvocationHandler接口,生成动态代理类

      动态代理类要动态生成。

      ClassLoader用来将动态的类加载到虚拟机(JVM)中。

      Proxy.newProxyInstance(类加载器《object.getClass.getClassLoder》,委托对象的接口《object.getClass().getInterfaces()》,this);

      动态创建代理类---方到实体类里面。

底层原理

 1.接口:

 ```java
package com.southwind.aop; 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);
}

2.代理对象:

 package com.southwind.aop;

 import java.lang.reflect.Array;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays; 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);
} @Override 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.println(method.getName()+"方法的参数是:"+ result); return result; } } ``` 3.实现类; ```java
package com.southwind.aop.impl; import com.southwind.aop.Cal; 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;
}
}

4.测试类:

```java
package com.southwind.test; import com.southwind.aop.Cal;
import com.southwind.aop.MyinvocationHandler;
import com.southwind.aop.impl.CalImpl; public class Test10 {
public static void main(String[] args) {
//实例化委托对象
Cal cal = new CalImpl();
// cal.add(10,3);
// cal.div(10,3);
// cal.mul(10,3);
// cal.sub(10,3);
// 获取代理对象
MyinvocationHandler myinvocationHandler= new MyinvocationHandler();
Cal proxy=(Cal)myinvocationHandler.bind(cal);
proxy.add(10,3); }
}

上述代码的动态机制实现了业务代码和非业务代码的解耦合,这是SpringAOP的底层实现机制,不要这么复杂,有更好的方式。

Spring AOP的开发步骤:

1.创建切面类:

package com.southwind.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component; import java.lang.reflect.Array;
import java.util.Arrays; @Component
@Aspect
public class LogAspect {
@Before("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void before(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
String args= Arrays.toString((joinPoint.getArgs()));
System.out.println(name+"方法的参数是"+args); }
@After("execution(public int com.southwind.aop.impl.CalImpl.*(..))")
public void after(JoinPoint joinPoint){
String name=joinPoint.getSignature().getName();
System.out.println(name+"方法执行完毕"); }
@AfterReturning(value = "execution(public int com.southwind.aop.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.southwind.aop.impl.CalImpl.*(..))",throwing = "ex")
public void afterTrowing(JoinPoint joinPoint,Exception ex){
String name= joinPoint.getSignature().getName();
System.out.println(name+"方法抛出异常"+ex);
} }

2.委托类加上@Component

package com.southwind.aop.impl;

import com.southwind.aop.Cal;
import org.springframework.stereotype.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;
}
}

3.配置spring.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 https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<!-- 扫包-->
<context:component-scan base-package="com.southwind.aop"></context:component-scan>
<!-- 自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

3测试类:

package com.southwind.aop.impl;

import com.southwind.aop.Cal;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test {
public static void main(String[] args) {
ApplicationContext applicationContext= new ClassPathXmlApplicationContext("spring-aop.xml");
Cal cal = (Cal)applicationContext.getBean("a");
System.out.println(cal.add(10,3));
} }
  • @Component 将切面类加载到IoC容器中
  • @Aspect 表示类是一个切面类
  • @Before 表示方法执行的时机,execution表示的是切入点是CallImpl中执行add方法之前执行日志方法
  • @AfterReturning,表示方法的执行时机是再业务方法返回结果:returning是将返回的业务代码的返回的形参
  • @AfterThrowing:表示方法执行是抛出的异常,throwing表示抛出的异常的处理形参
  • aop:aspectj-autoproxy ,Spring IoC容器会结合动态代理对象自动的生成代理对象,AOP底层就是通过动态代理对象来实现的。

    AOP的概念:

    • 切面对象;根据切面抽象出来的对象,Callmpl所有的方法中需要加入日志的部分,抽象成一个切面对象
    • 通知:切面对象具体执行的代码,即具体的非业务代码,LoggerAspect对象打印日志的代码
    • 目标;被横切的对象,即CallImpl将通知加入其中。
    • 代理:切面对象、通知、目标混合之后的结果,即时我门使用JDK动态代理的机制创建对象
    • 连接点;需要被横切的位置,即要通知要插入业务代码的具体位置

Spring(AOP的认识、实现)的更多相关文章

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

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

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

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

  3. spring aop

    什么是AOP AOP(Aspect-OrientedProgramming,面向方面编程),它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将 ...

  4. spring aop注解方式与xml方式配置

    注解方式 applicationContext.xml 加入下面配置 <!--Spring Aop 启用自动代理注解 --> <aop:aspectj-autoproxy proxy ...

  5. 基于Spring AOP的JDK动态代理和CGLIB代理

    一.AOP的概念  在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的 ...

  6. Spring AOP详解

    一.前言 在以前的项目中,很少去关注spring aop的具体实现与理论,只是简单了解了一下什么是aop具体怎么用,看到了一篇博文写得还不错,就转载来学习一下,博文地址:http://www.cnbl ...

  7. Spring AOP实例——异常处理和记录程序执行时间

    实例简介: 这个实例主要用于在一个系统的所有方法执行过程中出线异常时,把异常信息都记录下来,另外记录每个方法的执行时间. 用两个业务逻辑来说明上述功能,这两个业务逻辑首先使用Spring AOP的自动 ...

  8. 从零开始学 Java - Spring AOP 实现用户权限验证

    每个项目都会有权限管理系统 无论你是一个简单的企业站,还是一个复杂到爆的平台级项目,都会涉及到用户登录.权限管理这些必不可少的业务逻辑.有人说,企业站需要什么权限管理阿?那行吧,你那可能叫静态页面,就 ...

  9. 从零开始学 Java - Spring AOP 实现主从读写分离

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  10. 从零开始学 Java - Spring AOP 拦截器的基本实现

    一个程序猿在梦中解决的 Bug 没有人是不做梦的,在所有梦的排行中,白日梦最令人伤感.不知道身为程序猿的大家,有没有睡了一觉,然后在梦中把睡之前代码中怎么也搞不定的 Bug 给解决的经历?反正我是有过 ...

随机推荐

  1. C温故补缺(十六):未定义行为

    未定义行为 在计算机程序设计中,未定义行为是指执行某种计算机代码 所产生的结果,这种代码在当前程序状态下的行为在其所使用的语言标准中没有规定. 以C语言为例,未定义行为指C语言标准未作规定的行为,同时 ...

  2. 【PostgreSQL/PGSQL】创建分区表与临时表

    一.分区表 1.链接 https://blog.csdn.net/zhangyupeng0528/article/details/119423234 2.分类 列(值)分区表:partition by ...

  3. Thrift RPC添加access log

    前言: 当我们在部署web服务的时候,web容器通常都会记录来自客户端的访问日志.而当我们使用Thrift RPC服务的时候,Thrift服务则不会给我们自动记录客户端的访问日志. 通过这篇文章,你可 ...

  4. C/C++标准输入输出函数终极最全解析(不全捶我)

    C/C++的一众输入输出函数的区别常常搞得人晕头转向,二者之中又以输入函数更加令人头疼.本文尝试整理C/C++的各种输入输出函数. 由于输入涉及空格.换行符的读取.忽略等问题,因此输入比输出更麻烦.所 ...

  5. Clickhouse表引擎探究-ReplacingMergeTree

    作者:耿宏宇 1 表引擎简述 1.1 官方描述 MergeTree 系列的引擎被设计用于插入极大量的数据到一张表当中.数据可以以数据片段的形式一个接着一个的快速写入,数据片段在后台按照一定的规则进行合 ...

  6. python3使用OCR识别图片

    放假三天,闲来无事,想学下python爬虫.本想跟着网上教程操作一遍,奈何安装使用过程中出现一堆问题,并且在网上搜了一堆复制黏贴的答案,关键都不能起作用,最后终于找到一篇生效,为了以后不至于再经历这种 ...

  7. shape {select ...} append ({select ...} RELATE ID TO PARAMETER 0,ID TO PARAMETER 1)

    1.问题描述 最近在写vb.net的时候,碰到了一个有点棘手的问题.就是在vb里面去解决一对多的关系. 对应关系如下,一个合同会对应多个开票. 最简单暴力的方法就是循环查询了,但是这样子肯定不行的.如 ...

  8. 基本能看懂的C编译器,只有365行!

    Fabrice Bellard is a French computer programmer known for writing FFmpeg, QEMU, and the Tiny C Compi ...

  9. 经典 backbone 总结

    目录 目录 VGG ResNet Inceptionv3 Resnetv2 ResNeXt Darknet53 DenseNet CSPNet VoVNet 一些结论 参考资料 VGG VGG网络结构 ...

  10. python实现单向循环链表与双向链表

    目录 单向循环链表 操作 实现 双向链表 操作 实现 单向循环链表 单链表的一个变形是单向循环链表,链表中最后一个节点的next域不再为None,而是指向链表的头节点. 操作 is_empty() 判 ...