spring---AOP---学习记录---21.05.11

21.05.11

JoinPoint

指定通知方法中的参数:JoinPoint
* JoinPoint:业务方法,要加入切面功能的业务方法
* 作用是:可以在通知方法中获取方法执行时的信息,例如方法名称,方法的实参
* 如果你的切面功能中需要用到方法的信息,就加入JoinPoint
* 这个JoinPoint参数的值是由框架赋予,必须是第一个位置的参数

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">

    <!--把对象交给spring容器,由spring容器统一创建,管理对象-->
    <!--声明目标对象-->
    <bean id="someService" class="com.node.ba01.SomeServiceImpl"/>

    <!--声明切面类对象-->
    <bean id="myAspect" class="com.node.ba01.MyAspect" />

    <!--声明自动代理生成器-->
    <!--使用aspectj框架内部的功能,创建目标对象的代理对象
        创建代理对象是在内存中实现的,修改目标对象的内存中的结构。创建为代理对象,
        所以目标对象就是被修改后的代理对象

        aspectj-autoproxy:会把spring容器中的所有目标对象,一次性都生成代理对象
     -->
    <aop:aspectj-autoproxy />


</beans>

SomeService.java

package com.node.ba01;

public interface SomeService {
    void doSome(String name,Integer age);
}

SomeServiceImpl.java

package com.node.ba01;

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {

        //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
        System.out.println("===目标方法doSome===");
    }
}

MyAspect.java

package com.node.ba01;

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

import java.util.Date;

@Aspect
public class MyAspect {
    
    @Before(value="execution(void *..SomeServiceImpl.doSome(String,Integer))")
    public void myBefore(JoinPoint jp){

        //获取方法的完整定义
        System.out.println("方法的前面(定义)="+jp.getSignature());

        System.out.println("方法的名称="+jp.getSignature().getName());
        //获取方法的实参
        Object args[]=jp.getArgs();
        for(Object arg:args){
            System.out.println("参数="+arg);
        }
        //就是你切面要执行的功能代码
        System.out.println("切面功能:在目标方法之前输出执行时间:"+ new Date());
    }
}

测试代码

package com.node;

import com.node.ba01.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest01 {

    @Test
    public void test01(){

        String config="applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(config);
        //从容器中获取目标对象
        SomeService proxy= (SomeService) ac.getBean("someService");
        //通过代理的对象执行方法,事项目标方法执行时,增强了功能
        proxy.doSome("lisi",20);
    }
}

@AfterReturning 后置通知

@AfterReturning:后置通知
属性:
1. value 切入点表达式
2. returning 自定义的变量,表示目标方法的返回值的
自定义变量必须和通知方法的形参名一样

位置:在方法定义的上面

特点:1.在目标方法之后执行的
2.能够获取目标方法的返回值,可以根据这个返回值做不同的处理功能
3.可以修改这个返回值

SomeService.java

package com.node.ba02;

public interface SomeService {
    void doSome(String name,Integer age);

    String doOther(String name,Integer age);


}

SomeServiceImpl.java

package com.node.ba02;

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {

        //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
        System.out.println("===目标方法doSome===");
    }

    @Override
    public String doOther(String name, Integer age) {

        System.out.println("===目标方法doOther===");
        return "abcd";
    }
}

MyAspect.java

package com.node.ba02;

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

import java.util.Date;

@Aspect
public class MyAspect {


    @AfterReturning(value = "execution(* *..SomeServiceImpl.doOther(..))",
                    returning = "res")
   public void myAfterReturning(Object res){
       //Object res:是目标方法执行后的返回值,根据返回值做你的切面的功能处理
        System.out.println("后置通知:在目标方法之后执行的,获取的返回值是:"+res);
        if(res.equals("abcd")){
            //做一些功能
        }else{
            //做其他功能
        }
   }
}

测试代码

package com.node;

import com.node.ba02.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest02 {

    @Test
    public void test01(){

        String config="applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(config);
        //从容器中获取目标对象
        SomeService proxy= (SomeService) ac.getBean("someService");
        //通过代理的对象执行方法,事项目标方法执行时,增强了功能
        String str= proxy.doOther("zhangsan",30);
        System.out.println("str==="+str);

    }
}

@Around 环绕通知

环绕通知方法的定义格式
* 1.public
* 2.必须有一个返回值,推荐使用Object
* 3.方法名称自定义
* 4.方法有参数,固定的参数 proceedingJoinPoint
*
@Around : 环绕通知
* 属性:value 切入点表达式
* 位置:在方法定义的上面
* 特点:1.它是功能最强的通知
* 2.在目标方法前和后都能增强功能
* 3.控制目标方法是否被调用执行
* 4.修改原来的目标方法发的执行结果。影响最后的调用结果

环绕通知,等同于jdk动态代理的,InvocationHandler接口

参数:ProceedingJoinPoint 就等同于Method
作用:执行目标方法的
返回值:就是目标方法的执行结果,可以被修改

环绕通知:经常做事务,在目标方法之前开启事务,执行目标方法,在目标方法之后提交事务

SomeService.java

package com.node.ba03;

public interface SomeService {
    void doSome(String name,Integer age);

    String doOther(String name,Integer age);

    String doFirst(String name,Integer age);
}

SomeServiceImpl.java

package com.node.ba03;

public class SomeServiceImpl implements SomeService {
    @Override
    public void doSome(String name,Integer age) {

        //给doSome方法增加一个功能,在doSome()执行之前,输出方法的执行时间
        System.out.println("===目标方法doSome===");
    }

    @Override
    public String doOther(String name, Integer age) {

        System.out.println("===目标方法doOther===");
        return "abcd";
    }

    @Override
    public String doFirst(String name, Integer age) {
        System.out.println("===业务方法doFirst===");
        return "doFirst";
    }
}

MyAspect.java

package com.node.ba03;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import java.util.Date;

@Aspect
public class MyAspect {

    @Around(value = "execution(* *..SomeServiceImpl.doFirst(..))")
    public Object myAround(ProceedingJoinPoint pjp) throws Throwable {

        String name=null;
        Object args[]=pjp.getArgs();
        if(args!=null && args.length>1){
            Object arg=args[0];
            name=(String) arg;
        }
        //实现环绕通知
        Object result=null;
        System.out.println("环绕通知:在目标方法前,输出时间"+new Date());
        //1.目标方法调用
        if("zhaosi".equals(name)){
            //符合条件,调用目标方法
            result =pjp.proceed();//等同于method.invoke();或Object result=doFirst();
        }

        System.out.println("环绕通知:在目标方法后,输出时间");

        //2.在目标方法的前或后加入功能

        //修改目标方法的执行结果,影响方法的最后调用结果
        if(result!=null){
            result="123123";
        }

        //返回目标方法的执行结果
        return result;
    }
}

测试代码

package com.node;

import com.node.ba03.SomeService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest03 {

    @Test
    public void test01(){

        String config="applicationContext.xml";
        ApplicationContext ac=new ClassPathXmlApplicationContext(config);
        //从容器中获取目标对象
        SomeService proxy= (SomeService) ac.getBean("someService");
        //通过代理的对象执行方法,事项目标方法执行时,增强了功能
        String str= proxy.doFirst("zhaosi",40);//就是调用了myArround()
        System.out.println("str==="+str);

    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值