Spring-AOP面向切面编程

一、动态代理

程序在整个运行过程中不存在目标类的代理类,目标对象的代理对象只是由生成工具在程序运行时创建,代理对象与目标对象的代理关系在程序运行时才确定。

项目开发中。我们经常感觉交叉业务与主业务深度耦合在一起,当交叉业务较多时,主业务代码会出现大量交叉业务逻辑代码,大大降低程序可读性,后期维护也不方便,增加开发难度,所以采用动态代理,在不修改主业务的前提下,对功能的扩展

二、AOP

是Spring框架的核心功能之一,面向切面编程是从动态角度去考虑程序的运行过程,利用AOP可以对主业务逻辑的各个部分进行隔离
【举个例子】 如果我们开发的是一个转账的业务是,在转账的痛死我能需要考虑权限控制,日志管理,加载事务等机制,那么在转账业务的开发过程中充斥着大量非主业务逻辑代码,这样导致我们代码可读性非常差,并且在实际的项目统计中,非业务逻辑代码往往可以占到这个代码量一半,大大增加我们的开发难度。

AOP面向切面编程
1、减少重复代码
2、专注业务
在这里插入图片描述

三、AOP面向切面编程

①切面ASpect
切面泛指交叉业务 , 即对主业务逻辑功能的增强

②连接点JoinPoint
连接点指可以被切面织入的具体方法,通常业务接口中的方法可以看做连接点

③切入点Pointcut
多个连接点的集合
【*】被标记为 final 的方法是不能作为连接点与切入点的。因为最终的是不能被修改的,不能被增强的。

④目标对象Target
指将要被增强的对象,即包含主业务逻辑的类的对象

⑤通知(Advice)
通知
定义了增强代码切入到目标代码的时间点,是目标方法执行之前执行,还是之后执行等。通知类型不同,切入时间不同。
切入点定义切入的位置,通知定义切入的时间。

AspectJ对AOP的实现

对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一,可以完成面向切面编程。然而,AspectJ 也实现了 AOP 的功能,且其实现方式更为简捷,使用更为方便,
而且还支持注解式开发。所以,Spring 又将 AspectJ 的对于 AOP 的实现也引入到了自己的框架中。在 Spring 中使用 AOP 开发时,一般使用 AspectJ 的实现方式。

官网 地址:http://www.eclipse.org/aspectj/

五、AspectJ的通知类型
AspectJ 中常用的通知有五种类型:
(1)前置通知
(2)后置通知
(3)环绕通知
(4)异常通知
(5)最终通知

applicationContext.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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/aop
       http://www.springframework.org/schema/aop/spring-aop.xsd">

            <!--声明目标类对象-->
        <bean id="SomeServiceImpl" class="com.bjpowernode.ba01.SomeServiceImpl" />

            <!--声明代理类对象-->
        <bean id="Aspect" class="com.bjpowernode.ba01.MyAspect" />

            <!--声明自动代理生成器,创建目标对象的代理类-->
        <aop:aspectj-autoproxy proxy-target-class="true" />

</beans>

**
 * @Aspect : 表示当前类是切面类
 * 切面类, 是用来给业务方法增强功能的类, 把增强功能的代码写到切面类中
 */
@Aspect
public class MyAspect {

        @Before(value = "execution(* *..SomeServiceImpl.do*(..))")
        public void myBefore(JoinPoint jp){
        //要增强的代码
            System.out.println("执行增强功能的代码"+ new Date());

            //查看当前正在执行的目标方法
            System.out.println("执行方法:" + jp.getSignature().getName());
            System.out.println("方法定义:" + jp.getSignature());

            Object args[] = jp.getArgs();
            StringBuilder buider = new StringBuilder();

            for (Object arg : args) {
                buider.append(arg).append("#");
            }
            System.out.println(buider.toString());

    }
}

SomeService 接口

public interface SomeService {

    void dosome(String name , int age);

}

接口实现类,需要被增强的类(目标类)

public class SomeServiceImpl implements SomeService {

    @Override
    public void dosome(String name, int age) {
        System.out.println("执行了doSome方法添加业务的操作");
    }
}

自定义一个测试类

public class ba01Test {

    @Test
    public void test01(){

        String config = "applicationContext.xml";

        ApplicationContext ctx = new ClassPathXmlApplicationContext(config);

        SomeService proxy = (SomeService) ctx.getBean("SomeServiceImpl");

        proxy.dosome("zhangsan", 20);

    }
}

控制台输出结果:

执行增强功能的代码   2019-09-29 11:15:21
执行方法:dosome
方法定义:void com.bjpowernode.ba01.SomeServiceImpl.dosome(String,int)
zhangsan#20#
执行了doSome方法添加业务的操作


Process finished with exit code 0
后置通知
 //   AfterReturning
//    returning  表示方法的形参 后面的值必须跟方法的形参名相同
    @AfterReturning(
            value = "execution(* *..SomeServiceImpl.doTwo(..))",
            returning="ret"
    )
    public void  MyAfterReturning(Object ret){
        String param = null;
        if (ret != null) {
            param = (String) ret;
            param = param.toUpperCase();
        }
        System.out.println(param);
    }

@Aspect
public class MyAspect {
/*后置通知
*       AfterReturning
*       returning  表示方法的形参 后面的值必须跟方法的形参名相同
* */
    @AfterReturning(
            value = "execution(* *..SomeServiceImpl.doTwo(..))",
            returning="ret"
    )
    public void  MyAfterReturning(Object ret){
        String param = null;
        if (ret != null) {
            param = (String) ret;
            param = param.toUpperCase();
        }
        System.out.println(param);
    }
}
ic class MyAspect {
    /**
     * @AfterThrowing:异常通知
     *      value 切入点表达式
     *      Throwing 自定义的变量名,表示目标方法抛出的异常对象,必须和方法的参数名一样
     *特点   1.在目标方法抛出异常时执行的
     *      2、可以看做是对目标方法的监控
     *      3、不是异常处理程序,异常还是抛出了
     */
    @AfterThrowing(
            value="execution(*  *..SomeServiceImpl.doFour(..))",
            throwing ="ex"
    )
    public void MyAfterthrowing(Exception ex){
        System.out.println("异常通知:在目标方法执行时出现了异常"+ ex);

    }

}
/**
     * @After  最终通知  表示程序执行结束后一定会执行的方法
     */
    @After(value = "execution(* *..SomeService.doFive(..))")
    public void MyAfter(){
        System.out.println("最终通知,总是会执行的代码");
    }
}

以上就是Spring-AOP面向切面编程
AOP 为 Aspect Oriented Programming 的缩写,意为:面向切面编程,可通过运行期动态代理实现程序功能的统一维护的一种技术。AOP 是 Spring 框架中的一个重要内容。利用 AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

猜你喜欢

转载自blog.csdn.net/qq_42963930/article/details/101676671
今日推荐