AOP编程常规步骤

        这里基本上都是B站上孙哥Spring的视频,还有平时写代码总结来的。

AOP本质上是原始功能加上额外功能,使用的是代理模式的思想,一个典型的例子是:

  • 房东(原始功能)只想出租房子,但是嫌自己找租客太麻烦
  • 于是找到中介,中介替他去找租客(额外功能)

静态代理:

最开始是使用静态代理的模式:额外功能实现目标类相同的接口。缺点是要为每个原始类写一个代理类,并且修改扩展功能比较麻烦

public class User {}

public interface UserService {
	void test(User user);
}

public class UserServiceImpl implements UserService {
    @Override
    public void test(User user) {
        System.out.println("原始类的test方法》》》》》》》》》");
    }

}
/**
 * 静态代理类编码实现
 */
public class UserServiceProxy implements UserService { // 实现原始类相同的接口
    private UserService userService = new UserServiceImpl(); // 原始类
    @Override
    public void test(User user) {
        System.out.println("额外功能》》》》》》》"); // 额外功能
        userService.test(user);  //调用原始类的原始功能
    }

}

动态代理

针对静态代理出现的问题,有了Spring的动态代理开发。

步骤:

1,创建原始方法

2,定义额外功能

3,定义切入点(切入点表达式比较重要)

4,组合(把2,3对应起来)

使用Spring开发AOP有两种方式,XML和注解,

XML方式

(暂时不写了,除了最开始学习,平时工作也基本没用过这种方式)

注解方式

1,原始方法

        这个没什么说的,就是我们原来的方法

2,额外功能+切入点+组合

        

@Component
@Aspect  // 1.表示这是一个切面类
public class testAspect {

    @After(value = "execution(* com.mz.testSpring.controler.testSpringControler.sayHello(..))") //2.切入点表达式,标明原始方法位置
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("I'm fine ,thank you");
    }
}

          这里注意1和2两个地方,1表示这是一个切面类,2处的切入点表达式相当于XML方式的步骤3,4,也就是切入点和组合两部分组合起来了,加上下面的额外功能,相当于我们只要实现了这个切面类就实现了AOP编程的全部步骤,这样比XML方式方便的多,所以我在实际编码过程中XML方式一次也没有用过,不过想深入了解AOP的原理(其实就是上面代理模式+spring配置文件+反射那一套),还是需要了解下XML方式的。

        @After 后置通知,表示额外功能是在原始方法执行完之后执行的,与他相似的注解还有

        @Before   前置通知,原始方法之前执行

        @Around 环绕通知,在原始方法之前,之后都执行

        @AfterThrowing 异常通知,发生异常之后执行,我一般用它来手动回滚操作

切入点表达式:

  • execution()切入点函数

  • * *(..)切入点表达式

execution是切入点函数,也是功能最强大的,与他相似的还有args,within等(这几个我都没怎么用过,感觉一个execution就足够了)

        切入点表达式用来将额外功能定位到原始功能上,具体含义如下

* * (..)    --> 所有方法

*  --->  修饰符 返回值
*  --->  方法名
() --->  参数表
.. --->  对于参数没有要求 (参数有没有,参数有⼏个都行,参数是什么类型的都行)

一个例子:

* com.mz.testSpring.controler.testSpringControler.sayHello(..)

        表示我不在意返回值,额外功能对com.mz.testSpring.controler.testSpringControler类的sayHello方法生效,这里testSpringControler还可以换成*,表示controler包下的所有类,只要有sayHello方法,就对他的sayHello方法生效,或者sayHello也写成*,相当于包切入点,以此类推。最后一个参数,可以填写具体的参数类型。此外切入点表达式支持逻辑运算,如下

        

    @After(value = "execution(* com.mz.testSpring.controler.testSpringControler.sayHello(..))" +
            "       || execution(* com.mz.testSpring.controler.testSpringControler.sayGoodBye(..))")
    public void afterMethod(JoinPoint joinPoint){
        System.out.println("I'm fine ,thank you");

    }

测试

GET http://localhost:8080/test/sayGoodBye?name=Africa frends
Accept: application/json


###
GET http://localhost:8080/test/testAnno?name=Indian frends
Accept: application/json

AOP编程常规步骤_第1张图片

 AOP编程常规步骤_第2张图片

 

动态代理的底层:

  1. JDK:通过 实现接口,做新的实现类 创建代理对象

  2. Cglib:通过 继承父类,做新的子类 创建代理对象

基于注解的AOP开发可以通过设置配置文件来实现切换

下面是B站孙哥spring的一张总结图,感觉不错,粘过来了

AOP编程常规步骤_第3张图片

你可能感兴趣的:(java,代理模式,java,AOP,切入点表达式)