Spring AOP

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

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

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

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

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

AOP的优点:

  • 可以降低模块之间的耦合性

  • 提高代码的复用性

  • 集中管理代码的维护性

  • 集中管理代码的非义务代码,便于维护

  • 业务代码不受非业务代码的影响,逻辑更加清晰

    理解AOP

  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.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. spring框架 AOP核心详解

    AOP称为面向切面编程,在程序开发中主要用来解决一些系统层面上的问题,比如日志,事务,权限等待,Struts2的拦截器设计就是基于AOP的思想,是个比较经典的例子. 一 AOP的基本概念 (1)Asp ...

  2. Spring框架的核心功能之AOP技术

     技术分析之Spring框架的核心功能之AOP技术 AOP的概述        1. 什么是AOP的技术?        * 在软件业,AOP为Aspect Oriented Programming的 ...

  3. 跟着刚哥学习Spring框架--AOP(五)

    AOP AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善.OOP引入 ...

  4. 控制反转是Spring框架的核心。

    早在2004年,Martin Fowler就提出了“哪些方面的控制被反转了?”这个问题.他总结出是依赖对象的获得被反转了.基于这个结论,他为控制反转创造了一个更好的名字:依赖注入.许多非凡的应用(比H ...

  5. spring框架aop用注解形式注入Aspect切面无效的问题解决

    由于到最后我的项目还是有个邪门的错没解决,所以先把文章大概内容告知: 1.spring框架aop注解扫描默认是关闭的,得手动开启. 2.关于Con't call commit when autocom ...

  6. Spring 框架的核心功能之AOP技术

    1. AOP 的概述 AOP, Aspect Oriented Programming, 面向切面编程; 通过预编译方式和运行期动态代理实现程序功能的统一维护的技术; AOP 采取横向抽取机制,取代了 ...

  7. Spring框架的核心功能之AOP概述

    1. 什么是AOP的技术? * 在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程 * AOP是一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构 ...

  8. Spring框架——AOP代理

    我们知道AOP代理指的就是设计模式中的代理模式.一种是静态代理,高效,但是代码量偏大:另一种就是动态代理,动态代理又分为SDK下的动态代理,还有CGLIB的动态代理.Spring AOP说是实现了AO ...

  9. Spring框架-AOP详细学习[转载]

    参考博客:https://blog.csdn.net/qq_22583741/article/details/79589910#4-%E4%BE%9D%E8%B5%96%E6%B3%A8%E5%85% ...

  10. Spring框架 AOP面向切面编程(转)

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

随机推荐

  1. 二分查找-LeetCode704 简单题

    LeetCode代码链接:https://leetcode.cn/problems/binary-search/ 题目:给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ...

  2. 【Java并发入门】03 互斥锁(上):解决原子性问题

    原子性问题的源头是线程切换 Q:如果禁用 CPU 线程切换是不是就解决这个问题了? A:单核 CPU 可行,但到了多核 CPU 的时候,有可能是不同的核在处理同一个变量,即便不切换线程,也有问题. 所 ...

  3. Spring01:概述、工厂模式解耦、Spring中的IOC

    四天课程安排 第一天:Spring框架的概述.Spring中基于XML的IOC配置 第二天: Spring中基于注解的IOC和IOC的案例(单表增删改查,持久层随意) 第三天:Spring中的AOP和 ...

  4. MyBatis02:流程分析、注解、代理dao实现CRUD、参数深入、传统DAO、配置

    今日内容 回顾 mybatis的自定义.分析和环境搭建 完善基于注解的mybatis mybatis的curd(基于代理dao的方式)※ mybatis的参数深入及结果集的深入 mybatis中基于传 ...

  5. CPU 和 CPU Core 有啥区别?多核 CPU?多个 CPU?

    CPU 全称 Central Processing Unit,中央处理器,计算机的大脑,长这个样子: CPU 通过一个插槽安装在主板上,这个插槽也叫做 CPU Socket,它长这个样子: 而我们说的 ...

  6. MySQL数据结构(索引)

    目录 一:MySQL索引与慢查询优化 1.什么是索引? 2.索引类型分类介绍 3.不同的存储引擎支持的索引类型也不一样 二:索引的数据结构 1.二叉树(每个节点只能分两个叉) 2.数据结构(B树) 3 ...

  7. MySQL视图-触发器

    目录 一:视图 1.什么是视图? 2.为什么要用视图? 3.如何使用视图 4.反复拼接的繁琐(引入视图的作用) 5.解决方法 二:视图的应用 1.创建视图的格式: 2.查询视图层 3.查询Navica ...

  8. 模板层之标签 自定义过滤器及标签 模板的继承与导入 模型层之前期准备 ORM常用关键字

    目录 模板层之标签 if判断 for循环 自定义过滤器.标签及inclusion_tag(了解) 前期三步骤 自定义过滤器(最大只能接收两个参数) 自定义标签(参数没有限制) 自定义inclusion ...

  9. Win10下SDK Manager应用程序闪退问题的解决方法

    SDK Manager闪退原因:未找到Java的正确路径 解决办法: 1.在压缩包中找到Android.bat文件,右键编辑 2.打开的Android文件内容,找到如图的几行代码 将上面的代码替换成: ...

  10. Anaconda下载安装

    下载地址: 链接:https://pan.baidu.com/s/1fmJkMSL6amJF4KP5JwklOQ 提取码:dsyc 安装完成之后,记得配置系统环境变量: