AOP的快速入门(XML)
标签搜索
侧边栏壁纸
  • 累计撰写 21 篇文章
  • 累计收到 390 条评论

AOP的快速入门(XML)

limei
2023-09-10 / 0 评论 / 21 阅读 / 正在检测是否收录...

AOP的简介

  • AOP(Aspect Oriented Programing)面向切面编程,一种编程范式,隶属于软工范畴,指导开发者如何组织程序结构
  • AOP弥补了OOP的不足,基于OOP基础之上进行横向开发

    • uOOP规定程序开发以类为主体模型,一切围绕对象进行,完成某个任务先构建模型
    • uAOP程序开发主要关注基于OOP开发中的共性功能,一切围绕共性功能进行,完成某个任务先构建可能遇到的所有共性功能(当所有功能都开发出来也就没有共性与非共性之分)

AOP作用

  • 伴随着AOP时代的降临,可以从各个行业的标准化、规范化开始入手,一步一步将所有共性功能逐一开发完毕,最终以功能组合来完成个别业务模块乃至整体业务系统的开发
  • 目标:将软件开发由手工制作走向半自动化/全自动化阶段,实现“插拔式组件体系结构”搭建

AOP优势

  • 提高代码的可重用性
  • 业务代码编码更简洁
  • 业务代码维护更高效
  • 业务功能扩展更便捷

    AOP的相关概念

  • Joinpoint(连接点):就是方法
  • Pointcut(切入点):就是挖掉共性功能的方法
  • Advice(通知):就是共性功能,最终以一个方法的形式呈现
  • Aspect(切面):就是共性功能与挖的位置的对应关系
  • Target(目标对象):就是挖掉功能的方法对应的类产生的对象,这种对象是无法直接完成最终工作的
  • Weaving(织入):就是将挖掉的功能回填的动态过程
  • Proxy(代理):目标对象无法直接完成工作,需要对其进行功能回填,通过创建原始对象的代理对象实现
  • Introduction(引入/引介) :就是对原始对象无中生有的添加成员变量或成员方法
  • AOP开发过程

  • 开发阶段(开发者完成)

    • 正常的制作程序
    • 将非共性功能开发到对应的目标对象类中,并制作成切入点方法
    • 将共性功能独立开发出来,制作成通知
    • 在配置文件中,声明切入点
    • 在配置文件中,声明切入点通知间的关系(含通知类型),即切面
  • 运行阶段(AOP完成)

    • Spring容器加载配置文件,监控所有配置的切入点方法的执行
    • 当监控到切入点方法被运行,使用代理机制,动态创建目标对象代理对象,根据通知类别,在代理对象的对应位置将通知对应的功能织入,完成完整的代码逻辑并运行

AOP的通知类型5种

  • 前置通知:原始方法执行前执行,如果通知中抛出异常,阻止原始方法运行
    应用:数据校验
  • 格式:

    <aop:aspect ref="adviceId">
        <aop:before method="methodName" pointcut="……"/>
    </aop:aspect>
  • 说明:一个aop:aspect标签中可以配置多个aop:before标签
  • 基本属性:

    • method :在通知类中设置当前通知类别对应的方法
    • pointcut :设置当前通知对应的切入点表达式,与pointcut-ref属性冲突
    • pointcut-ref :设置当前通知对应的切入点id,与pointcut属性冲突
  • 后置通知:原始方法执行后执行,无论原始方法中是否出现异常,都将执行通知
    应用:现场清理
  • 格式:

    <aop:aspect ref="adviceId">
        <aop:after method="methodName" pointcut="……"/>
    </aop:aspect>
  • 说明:一个aop:aspect标签中可以配置多个aop:after标签
  • 返回后通知:原始方法正常执行完毕并返回结果后执行,如果原始方法中抛出异常,无法执行
    应用:返回- 格式:

    <aop:aspect ref="adviceId">
        <aop:after-returning method="methodName" pointcut="……"/>
    </aop:aspect>
  • 说明:一个aop:aspect标签中可以配置多个aop:after-returning标签
    值相关数据处理
  • 抛出异常后通知:原始方法抛出异常后执行,如果原始方法没有抛出异常,无法执行
    应用:对原始方法中出现的异常信息进行处理
  • 格式:

    <aop:aspect ref="adviceId">
        <aop:after-throwing method="methodName" pointcut="……"/>
    </aop:aspect>
  • 说明:一个aop:aspect标签中可以配置多个aop:after-throwing标签
  • 环绕通知:在原始方法执行前后均有对应执行执行,还可以阻止原始方法的执行
    应用:十分强大,可以做任何事情

    • 格式:
    <aop:aspect ref="adviceId">
        <aop:around method="methodName" pointcut="……"/>
    </aop:aspect>
  • 说明:一个aop:aspect标签中可以配置多个aop:around标签
    环绕通知的开发方式
  • 环绕通知是在原始方法的前后添加功能,在环绕通知中,存在对原始方法的显式调用

    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        Object ret = pjp.proceed();
        return ret;
    }
  • 环绕通知方法相关说明:

    • 方法须设定Object类型的返回值,否则会拦截原始方法的返回。如果原始方法返回值类型为void,通知方 也可以设定返回值类型为void,最终返回null
    • 方法需在第一个参数位置设定ProceedingJoinPoint对象,通过该对象调用proceed()方法,实现对原始方法的调用。如省略该参数,原始方法将无法执行
    • 使用proceed()方法调用原始方法时,因无法预知原始方法运行过程中是否会出现异常,强制抛出Throwable对象,封装原始方法中可能出现的异常信息

AOP的入门案例

案例目录结构

接口和接口实现类编写

package com.limei.service;

public interface UserService {
    public void save(int i,int m );
}
package com.limei.service.impl;

import com.limei.service.UserService;

public class UserServiceImpl implements UserService {
    public void save(int i,int m) {
        //0.将共性功能抽取出来
        //System.out.println("共性功能");
        System.out.println("user service running..."+i+","+m);
    }
}

AOP的通知类

package com.limei.aop;

import org.aspectj.lang.JoinPoint;

public class AOPAdvice {
    public void function(JoinPoint jp){
        Object[] args = jp.getArgs ();
        System.out.println("共性功能。。。"+args[0]);
    }

    public void before(int x,int y){
        System.out.println ("before..."+x+","+y);
    }
}

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:p="http://www.springframework.org/schema/p"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://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">

    <!--3.开启AOP命名空间-->
    <bean id="userService" class="com.limei.service.impl.UserServiceImpl"/>
    <!--2.配置共性功能成功spring控制的资源-->
    <bean id="myAdvice" class="com.limei.aop.AOPAdvice"/>

    <!--4.配置AOP-->
    <aop:config>
        <!--5.配置切入点-->
        <aop:pointcut id="pt" expression="execution(* *..*(..))"/><!--关键字(访问修饰符 返回值 包名.类名.方法名(参数) 异常名)-->
        <!--6.配置切面(切入点与通知的关系)-->
        <aop:aspect ref="myAdvice">
            <!--7.配置具体的切入点对应通知中那个操作方法-->
            <aop:before method="function" pointcut-ref="pt"/>

            <aop:before method="before" pointcut="execution(* *..*(int,int))&amp;&amp;args(x,y)"></aop:before>
        </aop:aspect>
    </aop:config>

</beans>

启动类

import com.limei.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext ( "applicationContext.xml" );
        UserService userService = (UserService) ctx.getBean ( "userService" );
        userService.save (666,777);
    }
}
0

评论 (0)

取消