spring 面向切面编程(aop)

一、AOP术语

1、通知(advice)

切面的工作被称为通知。通知定义了切面是什么以及何时使用。除了描述切面要完成的工作,通知还定义了何时执行这个工作。
Spring切面可以应用五种类型的通知:

  • 前置通知(before):在目标方法被调用之前调用的通知;
  • 后置通知(after):在目标方法成功执行之后调用,此时不会关心方法的返回是什么;
  • 返回通知(after-returning):在目标方法成功执行之后调用;
  • 异常通知(after-throwing):在目标方法抛出异常后调用通知;
  • 环绕通知(around):通知包裹了目标方法,在目标方法调用之前和之后执行自定义行为,可以决定是否执行目标方法。
2、连接点(join point)

就是指spring允许你使用通知的地方

3、切点(point cut)

切点定义何时使用通知。切点的定义会匹配通知所要织入的一个或多个连接点。可以动态的决定是否使用通知

4、切面(aspect)

切面是切点和通知的结合。

5、引入(introduction)

引入允许我们向目标类添加新的方法和属性,在不修改现有类的情况下,让他们具有新的行为和状态

6、织入(weaving)

织入是把切面应用到目标对象并创建新的代理对象的过程。切面在指定的连接点被织入到目标对象中。在目标对象的生命周期里有多少个点可以织入:

  • 编译期:切面在目标类的编译时被织入。这种方式需要特殊的编译器。AspectJ的织入编译器就是以这种方式织入切面的
  • 类加载期:切面在目标类加载到JVM时被织入。这种方式需要特殊的类加载器(ClassLoader),它可以在目标类被引入应用之前增强该类的字节码。AspectJ5的加载时织入(load-time weaving,LTW)就是支持这种方式
  • 运行期:切面在应用运行的某个时刻被织入。一般情况下,在织入切面时,AOP会为目标类对象动态的创建一个代理对象。Spring AOP就是以这种方式。

二、指示器

Spring借助AspectJ的切点表达式语言来定义Spring切面

  • args():限制连接点匹配参数为指定类型的执行方法
  • @args():限制连接点由指定注解标注的执行方法,支持只有一个入参,且参数类持有指定注解
  • execution():用于匹配是连接点的执行方法
  • this():限制连接点匹配AOP代理的bean引用为指定类型的类
  • target():限制连接点匹配对象为指定类型的类
  • @target():限制连接点匹配特定的目标对象,要有指定的注解
  • within():限制连接点匹配指定的类型
  • @within():限制连接点匹配指定注解所标注的类型
  • @annotation():限制匹配带有指定注解的连接点

三、编码使用

1、execution+args

定义一个重载的三个方法,用于验证args

@Service("aopDemo1Service")
public class AopDemo1ServiceImpl implements IAopDemoService {
    @Override
    public String getDemo() {
        System.out.println("demo1 start..............");
        System.out.println("我是没有入参的demo");
        System.out.println("demo1 end..............");
        return "no param!";
    }

    @Override
    public String getDemo(String arg1) {
        System.out.println("demo1 start..............");
        System.out.println("我是有一个入参的demo,入参是:" + arg1);
        System.out.println("demo1 end..............");
        return "one param!";
    }

    @Override
    public String getDemo(int arg1, String arg2) {
        System.out.println("demo1 start..............");
        System.out.println("我是有两个入参的demo,第一个参数:" + arg1 + "\n第二个参数:" + arg2);
        System.out.println("demo1 end..............");
        return "two params!";
    }
}

切面配置

@Aspect
@Component
public class AopConfigDemo {
    @Pointcut("execution(* com.wfs.springboot.aop.*.getDemo(..))")
    public void pointCut() {

    }
	/**
     * args 用于匹配到第一个参数为Integer、第二个参数为String的连接点
     * @param joinPoint
     * @param arg1
     * @param arg2
     */
    @Around(value = "pointCut() && args(arg1,arg2)")
    public void around(ProceedingJoinPoint joinPoint, Integer arg1,String arg2) {
        System.out.println("aop start................");
        try {
            Object proceed = joinPoint.proceed();
            System.out.println("目标方法返回值:" + proceed);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("aop end................");
    }
}
2、使用自定义注解@annotation

在类上和方法上加上注解

@Service("aopDemo2Service")
@AopAnnotation
public class AopDemo2ServiceImpl implements IAopDemoService{

    @Override
    @AopAnnotation
    public String getDemo() {
        System.out.println("demo2 start..............");
        System.out.println("我是没有入参的demo");
        System.out.println("demo2 end..............");
        return "no param!";
    }

    @Override
    public String getDemo(String arg) {
        System.out.println("demo2 start..............");
        System.out.println("我是有一个入参的demo,入参是:" + arg);
        System.out.println("demo2 end..............");
        return "one param!";
    }

    @Override
    public String getDemo(int arg1, String arg2) {
        System.out.println("demo2 start..............");
        System.out.println("我是有两个入参的demo,第一个参数:" + arg1 + "\n第二个参数:" + arg2);
        System.out.println("demo2 end..............");
        return "two params!";
    }

aop配置

	/**
     * 只有方法上有注解才会使用切面
     */
	@Pointcut("@annotation(com.wfs.springboot.annotation.AopAnnotation)")
    public void pointCut() {

    }

    /**
     * args 用于匹配到第一个参数为Integer、第二个参数为String的连接点
     * @param joinPoint
     */
    @Around(value = "pointCut()")
    public void around(ProceedingJoinPoint joinPoint) {
        System.out.println("aop start................");
        try {
            Object proceed = joinPoint.proceed();
            System.out.println("目标方法返回值:" + proceed);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("aop end................");
    }
3、@winthin、winthin
	/**
     * 使用@within 当前注解的类所有方法都会被织入
     */
    @Pointcut("@within(com.wfs.springboot.annotation.AopAnnotation)")
    public void pointCut() {

    }
   /**
     * IAopDemoService类型及子类型的任何方法
     */
	@Pointcut("within(com.wfs.springboot.aop.IAopDemoService+)")
    public void pointCut() {

    }

within支持表达式,类似execution

4、@args

仅支持只有一个入参的方法,并且参数类上必须持有定义的注解
aop配置

@Around(value = "pointCut() && @args(com.wfs.springboot.annotation.AopAnnotation)")
    public void around(ProceedingJoinPoint joinPoint) {
        System.out.println("aop start................");
        try {
            Object proceed = joinPoint.proceed();
            System.out.println("目标方法返回值:" + proceed);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        System.out.println("aop end................");
    }

入参类

@Data
@AopAnnotation
public class User {

    private String name;

    private SexEnum sex;
}

调用方法

	@Override
    public void getDemo(User user) {
        System.out.println("我有带注解的入参");
    }
5、this

只支持全限定名,不支持通配符;是对代理对象类型的匹配所以包括接口类型也匹配
当前目标对象实现了IAopDemoService接口的任何方法

@Pointcut("this(com.wfs.springboot.aop.IAopDemoService)")
    public void pointCut() {

    }
6、target、@target

只支持全限定名,不支持通配符;是对目标对象类型的匹配所以不包括接口类型匹配

    @Pointcut("target(com.wfs.springboot.aop.AopDemo1ServiceImpl)")
    public void pointCut() {

    }
	@Pointcut("within(com.wfs.springboot.aop.IAopDemoService+) && @target(com.wfs.springboot.annotation.AopAnnotation)")
    public void pointCut() {

    }

@target不能单独使用,启动会报错

7、bean

支持通配符

	/**
     * 表示bean的id或者名称为aopDemo1Service
     */
    @Pointcut("bean(aopDemo1Service)")
    public void pointCut() {

    }

四、通知参数

public interface JoinPoint {
	// 连接点的信息execution(String com.wfs.springboot.aop.AopDemo1ServiceImpl.getDemo(String))
    String toString();
    //连接点简要信息 execution(AopDemo1ServiceImpl.getDemo(..))
    String toShortString();
	//连接点详细信息execution(public java.lang.String com.wfs.springboot.aop.AopDemo1ServiceImpl.getDemo(java.lang.String))
    String toLongString();
	//返回代理对象
    Object getThis();
	//返回目标对象
    Object getTarget();
	// 返回目标参数
    Object[] getArgs();
	// 返回当前连接点的签名
    Signature getSignature();
	// 返回连接点在类文件中的位置
    SourceLocation getSourceLocation();
	//连接点类型 method-execution
    String getKind();
	// 返回连接点静态部分
    JoinPoint.StaticPart getStaticPart();
public interface Signature {
    //String com.wfs.springboot.aop.AopDemo1ServiceImpl.getDemo(int,String)
    String toString();
	//AopDemo1ServiceImpl.getDemo(..)
    String toShortString();
	//public java.lang.String com.wfs.springboot.aop.AopDemo1ServiceImpl.getDemo(int,java.lang.String)
    String toLongString();
	// 方法名 getDemo
    String getName();
	// 表示修饰符  1
    int getModifiers();
	// 目标类
    Class getDeclaringType();
	// 目标类全限定名
    String getDeclaringTypeName();
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值