我的编程空间,编程开发者的网络收藏夹
学习永远不晚

java开发AOP面向切面编程入门

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

java开发AOP面向切面编程入门

引言

在实际应用场景中,我们封装一个学生的类,这个类用于封装学生的日常行为,如:上学、吃饭、上课等。然而,在疫情期间,学生上学时入校、吃饭时进入餐厅,需要测温查验证件等行为,拿到这样的需求我们怎么办?

不好的解决方案

面向过程的解决方案

遇到问题解决问题,在上学、吃饭方法中加上测温、查验证件方法,或者在学生类中提炼一个测温查验证件私有的方法,在需要时调用。

代码如下:


public class Student {
    public void toSchool(){
        check();
        System.out.println("高高兴兴去上学!");
    }
    public void toEat(){
        check();
        System.out.println("一号餐厅去吃饭!");
    }

    public void toClass(){
        System.out.println("排排坐,听讲座!");
    }

    public void getUp(){
        System.out.println("起床啦!");
    }
    
    private void check(){
        System.out.println("查验证件、测体温");
    }
}

这种方式存在问题只是头痛医头、脚痛医脚,代码硬拷贝,现在教师进校门也要查验证件测温,如何办?将check代码复制到教师类中,再者,如果check()中业务规则发生变化,则需要到处改代码,显然是一种非常蹩脚的解决方案。

使用继承解决方案

创建一个man的基类,将check()方法放到该类中,教师、学生均继承此类,子类调用这个方法即可,

代码如下:


public class Man {
    protected void check(){
        System.out.println("查验证件、测体温");
    }
}

public class Student extends Man {

    public void toSchool(){
        check();
        System.out.println("高高兴兴去上学!");
    }

    public void toEat(){
        check();
        System.out.println("一号餐厅去吃饭!");
    }
}

public class Teacher extends Man {
    public void toSchool(){
        check();
        System.out.println("高高兴兴去上班!");
    }

    public void toEat(){
        check();
        System.out.println("教工餐厅去吃饭!");
    }

    public void toClass(){
        System.out.println("排排坐,听讲座!");
    }
}

这种方式,虽然解决了代码复制问题,但违背了面向对象程序设计的单一职责原则,因为查验证件测温等均不是学生或教师应该拥有的职责,类的划分职责不清,增加了代码扩展维护的难度。

使用聚合的解决方案

将查验证件测温等行为封装一个独立的类,学生和教师的依然只封装他们固有的方法,

代码如下:


public class Checktor {
    public void takeTemperature(){
        System.out.println("查验证件、测体温");
    }
}
public class Student {
    private Checktor checktor = new Checktor();

    public void toSchool(){
        checktor.takeTemperature();
        System.out.println("高高兴兴去上学!");
    }

    public void toEat(){
        checktor.takeTemperature();
        System.out.println("一号餐厅去吃饭!");
    }
}

这种方法很好的解决了面向对象程序设计单一职责原则,体现了类的封装性,但是代码侵入性很强,而且代码僵化,维护性差。如疫情结束了,我们要求取消查验证件和测温,就需要改原有的代码,破坏了开闭原则,增加了程序员的工作量。有些人写配置开关变量,在调用时使用ifelse进行判断是否调用也能遵循开关变量,但是代码中包含了一些可能用不到代码,不优雅,不是很好解决方案。

面向切面的编程基本概念

面向切面的编程是不破坏原有类封装性的前提下,动态在其方法前面(before)、后边(after)及周围(Around)(前面和后边)增强功能。

  • 连接点(Joinpoint):目标对象中每个方法前面、后面均为连接点。如学生类中toSchool、toEat、toClass、getUp方法前面后面均是切入点;
  • 切入点(Point):需要增强功能方法前面或后面,是切入点,如进学校前、吃饭前需要测体温,则toSchool、toEat两个方法前是切入点,其余的不是;

在这里插入图片描述

  • 切面类(Aspect):也称通知类,封装了需要增强功能的类,如:Checktor;
  • 通知方法(advice):需要增强的功能,如:测温方法;
  • 通知类型:前置通知(Before)、后置通知(After)、环绕通知(around)、异常通知(throwing)、最终通知(after (finally) advice);

在这里插入图片描述

  • 代理(proxy):将通知应用到目标对象实现机制,是通过创建代理对象完成的
  • 织入(Weaving):将切面代码插入到目标对象上,生成代理对象的过程

基于Spring面向切面程序实现

针对学生上学场景,Spring的使用XML和注解两设计种方式完成面向切面的编程。
工程依赖项:在maven pom文件中,需要引入以下依赖项


     <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjtools</artifactId>
      <version>1.8.9</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjrt</artifactId>
      <version>1.5.4</version>
    </dependency>

    <dependency>
      <groupId>org.aspectj</groupId>
      <artifactId>aspectjweaver</artifactId>
      <version>1.9.5</version>
      <scope>runtime</scope>
    </dependency>

XML方式:
学生类:


public class Student {

    public void toSchool(){
        System.out.println("高高兴兴去上学!");
    }

    public void toEat(){
        System.out.println("一号餐厅去吃饭!");
    }

    public void toClass(){
        System.out.println("排排坐,听讲座!");
    }

    public void getUp(){
        System.out.println("起床啦!");
    }
}

切面类:


public class Checktor {
    public void takeTemperature(){
        System.out.println("测体温啦!");
    }

    public void washHand(){
        System.out.println("洗洗手更健康!");
    }
}

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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
    <context:component-scan base-package="com.bjwl.*"/>
    <!--目标(业务)对象-->
    <bean id="student" class="com.bjwl.xmltest.Student"/>
    <bean id="teacher" class="com.bjwl.xmltest.Teacher"/>
    <!--通知(切面)对象-->
    <bean id="checktor" class="com.bjwl.xmltest.Checktor"></bean>

    <aop:config>
        <!--定义(切面)对象-->
        <aop:aspect ref="checktor">
            <!--定义切点-->
            <aop:pointcut id="point_test_d" expression="execution(* com.bjwl.xmltest.Student.to*(..))"/>
            <!--定义通知-->
            <aop:before method="takeTemperature" pointcut-ref="point_test_d"></aop:before>
            <aop:after method="washHand" pointcut-ref="point_test_d"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

其中:目标对象是student对象,切点是student对象中方法名前两个字母是to的所有方法,事前执行测温(takeTemperature)、事后执行洗手(washHand)
测试代码如下:


public class StudentTest {
    @Test
    public void toSchool() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "bean02.xml"
        );
        Student student = (Student)applicationContext.getBean("student");
        student.toSchool();
    }
 } 

运行结果如下:

在这里插入图片描述

如果教师需也需要测温,编写教师类,代码如下:


public class Teacher {
    public void toSchool(){
        System.out.println("高高兴兴去上班!");
    }

    public void toEat(){
        System.out.println("教工餐厅去吃饭!");
    }

    public void toClass(){
        System.out.println("排排坐,听讲座!");
    }
}

xml文件更改如下:


    <aop:config>
        <!--定义(切面)对象-->
        <aop:aspect ref="checktor">
            <!--定义切点-->
            <aop:pointcut id="point_test_d" expression="execution(* com.bjwl.xmltest.*.to*(..))"/>
            <!--定义通知-->
            <aop:before method="takeTemperature" pointcut-ref="point_test_d"></aop:before>
            <aop:after method="washHand" pointcut-ref="point_test_d"></aop:after>
        </aop:aspect>
    </aop:config>

则表示com.bjwl.xmltest中的所有类的对象均为目标对象,前两个字母带to的方法前后均为切点。

注解方式:
学生类代码:

在这里插入图片描述

切面类的代码

在这里插入图片描述

xml文件:

在这里插入图片描述

运行结果等同,XML文件。

这样做的好处,学生类、教师类、切面类具有职责单一性,提现业务逻辑封装性,动态增强符合开闭原则。

小结

以上简单的介绍了面向切面编程的基本概念和基本用法。用好面向切面的编程技术很不易,因为切点只能设置到需要增强功能前面或后面,对程序设计人员要求很高,要求能够根据编程经验和技巧设计出合理的切点,需要提现类的层次性。如:执行SQL语句前,在控制台输出完整的SQL语句的切点,切点就不能设置到你自己定义的Dao中,而是设置在PrepareStatement的exectuce的方法前。不过也不用担心,使用各种框架时,常用的日志等,已经给我们设置了开关变量,我们直接使用即可,非常简单。

以上就是java开发AOP面向切面编程入门的详细内容,更多关于java面向切面编程的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

java开发AOP面向切面编程入门

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Java面向切面编程AOP怎么实现

这篇文章主要介绍“Java面向切面编程AOP怎么实现”,在日常操作中,相信很多人在Java面向切面编程AOP怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java面向切面编程AOP怎么实现”的疑惑有所
2023-06-04

【Spring】面向切面编程详解(AOP)

文章目录 一、AOP概述什么是AOPAOP应用场景 二、AOP的基本术语术语介绍术语举例详解 三、AOP实例说明四、通知类型详解概述前置通知后置通知环绕通知最终通知 六、AOP实现声明式事务
2023-08-30

Java aop面向切面编程有什么特点

面向切面编程(AOP)是一种软件开发范式,用于将横切关注点(cross-cutting concerns)与主要业务逻辑分离。AOP 可以在不改变原始代码的情况下,通过引入切面(aspect)对应用程序进行功能增强、横切关注点的处理等操作
Java aop面向切面编程有什么特点
2024-03-01

Springboot怎样使用Aspectj实现AOP面向切面编程

Springboot怎样使用Aspectj实现AOP面向切面编程,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。要在 Springboot中声明 AspectJ 切面需在 IOC
2023-06-22

Python面向切面编程AOP及装饰器怎么使用

本篇内容主要讲解“Python面向切面编程AOP及装饰器怎么使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“Python面向切面编程AOP及装饰器怎么使用”吧!什么是 AOPAOP,就是面向切
2023-06-30

Java面向切面编程怎么实现

在Java中实现面向切面编程,可以使用以下几种方式:1. 使用代理模式:通过创建代理类,将横切逻辑封装在代理类中,然后在实际业务类中使用代理类进行调用。代理类可以使用Java提供的动态代理(java.lang.reflect.Proxy)或
2023-08-08

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录