欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

面向切面 AOP编程详解

程序员文章站 2022-06-04 21:58:31
...

        AOP(Aspect Orient Programming),面向切面编程。面向切面编程是从动态角度考虑程序的运行过程。

        AOP底层,就是采用的动态代理模式实现的。采用了两种代理:JDK的动态代理,CGLib的动态代理

        AOP的作用:利用AOP对业务逻辑的各个部分进行隔离,降低业务逻辑的耦合性,提高程序的可重用型和开发效率。

AOP编程有什么好处???

1、减少重复代码

2、专注业务开发

Tip:AOP只是对OOP的一种补充

AOP编程术语

1、切面(Aspect)

        切面通常是交叉业务逻辑中的,横向开发,像日志、事务的处理,是对业务逻辑的增强

2、连接点(JoinPoint)

        连接点是可以被植入具体业务方法的,这些方法都是连接点

3、切入点(Pointcut)

        切入点指声明一个或多个连接点的集合

4、目标对象(Target)

        就是将要被增强的对象

5、通知(Advice)

        通知是定义了增强代码切入到目标代码的时间点,是放在目标对象执行前、后的

        AOP常见的通知
@Before 前置通知   方法执行前调用  对应注解
@After 后置通知   方法执行后调用  对应注解
@AfterReturning 返回通知   方法返回后调用  对应注解
@AfterThrowing 异常通知   方法出现异常调用 对应注解

@Around 环绕通知   动态代理、手动推荐方法运行 对应注解

需要引入pom文件的jar包

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.6</version>
    </dependency>

AspectJ的切入点表达式

        AspectJ定义了专门的表达式,用于指定切入点,表达式原型为

execution([modifiers-pattern] // 访问权限类型
          ret-type-pattern // 返回值类型
          [declaring-type-pattern] // 全限定性类名
          name-pattern(param-pattern) // 方法名(参数类型和参数个数)
          [throws-pattern] // 抛出异常
          )

/**
* 切入点表达式要匹配的对象就是目标方法的方法名。所以,execution表达式中明显就是方法的签名
* 注意,表达式中加[]的部分表示可省略部分,各部分间用空格分开。在其中可以使用以下符号:
*/

面向切面 AOP编程详解

例如,我们要给某个业务方法加上前置通知

1、准备一个Demo,定义一个切面类

  Service层和实现层

package com.serivce;

public interface SomeService {
    void doSome(String name, Integer age);
}
package com.serivce;


public class SomeServiceImpl implements SomeService {

    public void doSome(String name,Integer age) {
        System.out.println("doSome的的业务方法");
    }
}

 定义切面类

package com.aspect;


import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect // 声明这是一个切面类,做业务增强的
public class MyAspect {

    // 定义一个方法,贴上@Before注解,设置需要前置通知的类
    // 在这个方法中写入需要增强的功能,如日志,事务
    @Before(value = "execution(* com.serivce.SomeServiceImpl.doSome(..))")
    public void myBefore(JoinPoint jp){ // JoinPint jp 是连接点,做其他功能的,暂时忽略
        System.out.println("前置通知:在目标方法之前,执行日志的功能");

        // 连接点方法的定义
        System.out.println("连接点方法的定义:"+jp.getSignature());
        // 连接点方法的名称
        System.out.println("连接点方法的名称:"+jp.getSignature().getName());

        // 获取方法执行时的参数
        Object args [] = jp.getArgs();
        for (Object arg : args) {
            System.out.println(arg);
        }
    }
}

2、在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 https://www.springframework.org/schema/aop/spring-aop.xsd">
<!--声明目标类对象-->
    <bean id="someService" class="com.serivce.SomeServiceImpl"/>
<!--声明切面类对象-->
    <bean id="myaspect" class="com.aspect.MyAspect"/>

<!--    声明自动代理生成器:使用aspectj把spring容器中目标类对象生成代理-->
    <aop:aspectj-autoproxy/>

</beans>

3、测试

    @Test
    public void Test01(){
        SomeService someService = (SomeService) ctx.getBean("someService");

        someService.doSome("海百万",28);
    }
}

 结果如下

面向切面 AOP编程详解