Spring AOP(一)五种增强(Advice)

导读:本篇文章讲解 Spring AOP(一)五种增强(Advice),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

AOP术语都非常抽象,结合某些小例子就会形象、具体一些。

连接点(Joinpoint)

Spring仅支持方法的连接点,即仅能在方法调用前、方法调用后、方法抛出异常时及方法调用前后,这些程序执行点织入增强。
黑客攻击系统需要找到突破口,从某种程度上来说,AOP也可以看成一个黑客(因为它要向目标类中嵌入额外的代码逻辑),而连接点就是AOP向目标类打入楔子的候选锚点。

接口名:org.aspectj.lang.JoinPoint

在这里插入图片描述
其中,最常用的是以下几个:

  • getArgs()
  • getTarget()
  • getSignature()

相关接口:org.aspectj.lang.ProceedingJoinPoint extends JoinPoint
在这里插入图片描述
其中,最常用的是以下几个:

  • proceed()
  • proceed(Object[])

小例子(环绕增强)

public class UserInfo {
    private String name;

    public UserInfo(String name) {
        this.name = name;
    }
...
}
public interface IBaseMapper {
    void insert(UserInfo userInfo);
}
public interface IOrderMapper extends IBaseMapper {
    void save(String name, Integer age);
}
@Service
public class OrderMapperService implements IOrderMapper {
    @Override
    public void save(String name, Integer age) {
        System.out.println("### 进入save(..),name=" + name);
    }

    @Override
    public void insert(UserInfo userInfo) {
        System.out.println("### 进入insert(..)");
    }
}
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

@Aspect
@Component
public class OrderAspect {

    // 也可以先自定义注解,再:@Pointcut("@annotation(com.xxx.MyAnnotation)")
    @Pointcut(value = "execution(* com.javatpoint.service.IOrderMapper.*(..))")
    private void logDisplayingBalance() {
    }

    @Around(value = "logDisplayingBalance()")
    public void aroundAdvice(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("### The method aroundAdvice() before invokation of the method " + jp.getSignature().getName() + " method");
        try {
            jp.proceed();
        } finally {
        }

        // ProceedingJoinPoint的常用方法
        Object[] args = jp.getArgs();
        MethodSignature methodSignature = (MethodSignature)jp.getSignature();
        Method method = methodSignature.getMethod();
        Class<?>[] parameterTypes = method.getParameterTypes();
        Object target = jp.getTarget();

        // 模拟:修改为大写后,再次重复执行
        repeatExecuteMethod(target, method, args);

        System.out.println("### The method aroundAdvice() after invokation of the method " + jp.getSignature().getName() + " method");
    }

    /**
     * 重复执行
     * 可以加入一些特殊处理,例如:小写转大写、加密、脱敏处理等
     * @param target
     * @param method
     * @param args
     * @return
     */
    public Object repeatExecuteMethod(Object target, Method method, Object[] args) {
        try {
            Object invoke = method.invoke(target, toUpperCase(args));
            return invoke;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Object[] toUpperCase(Object[] args) {
        if (args == null || args.length == 0) {
            return args;
        }

        List<Object> list = new ArrayList<>();

        for (Object obj : args) {
            if (obj instanceof String) {
                String obj2Str = (String)obj;
                list.add(obj2Str.toUpperCase());
            } else {
                list.add(obj);
            }
        }

        return list.toArray();
    }
}

import com.javatpoint.service.IOrderMapper;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import com.javatpoint.service.BankService;

@SpringBootApplication
// @EnableAspectJAutoProxy annotation enables support for handling the components marked with @Aspect annotation.
// It is similar to tag in the xml configuration.
@EnableAspectJAutoProxy
public class AopAroundAdviceExampleApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(AopAroundAdviceExampleApplication.class, args);

        IOrderMapper order = context.getBean(IOrderMapper.class);
        order.save("yaoyao", 12);
        order.insert(new UserInfo("jjk"));

        context.close();
    }
}

前置增强

@Aspect
@Component
public class EmployeeServiceAspect {

	@Before(value = "execution(* com.javatpoint.service.EmployeeService.*(..)) and args(empId2, fname, sname)")
	public void beforeAdvice(JoinPoint joinPoint, String empId2, String fname, String sname) {
		System.out.println("Before method:" + joinPoint.getSignature());
		System.out.println("Creating Employee with first name - " + fname + ", second name - " + sname + " and id - " + empId2);
	}
}

注意上面“ and args ”的用法,不是EmployeeService类的所有方法都增强,仅仅是三个参数,且三个String类型的方法才增强。

后置增强

@Aspect
@Component
public class EmployeeServiceAspect {
	@After(value = "execution(* com.javatpoint.service.EmployeeService.*(..)) and args(empId, fname, sname)")
	public void afterAdvice(JoinPoint joinPoint, String empId, String fname, String sname) {
		System.out.println("After method:" + joinPoint.getSignature());
		System.out.println("Successfully created Employee with first name - " + fname + ", second name - " + sname + " and id - " + empId);
	}
}

方法返回值前增强

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import com.javatpoint.model.Account;

@Aspect
@Component
public class AccountAspect {
    //implementing after returning advice
    @AfterReturning(value = "execution(* com.javatpoint.service.impl.AccountServiceImpl.*(..))", returning = "account")
    public void afterReturningAdvice(JoinPoint joinPoint, Account account) {
        System.out.println("After Returing method:" + joinPoint.getSignature());
        System.out.println(account);
    }

抛出异常增强

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AccountAspect {
    //implementing after throwing advice	
    @AfterThrowing(value = "execution(* com.javatpoint.service.impl.AccountServiceImpl.*(..))", throwing = "ex")
    public void afterThrowingAdvice(JoinPoint joinPoint, Exception ex) {
        System.out.println("After Throwing exception in method:" + joinPoint.getSignature());
        System.out.println("Exception is:" + ex.getMessage());
    }
}

资料

  • https://www.javatpoint.com/spring-boot-aop

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/17221.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!