西三环路网站建设,网站建设需要几个人,一台主机做两个网站,莱芜做网站公司前言 接触过Spring的都知道#xff0c;aop是其中重要的特性之一。笔者在开发做项目中#xff0c;aop更多地是要和注解搭配#xff1a;在某些方法上加上自定义注解#xff0c;然后要对这些方法进行增强(很少用execution指定#xff0c;哪些包下的哪些方法要增强)。那这时就…前言 接触过Spring的都知道aop是其中重要的特性之一。笔者在开发做项目中aop更多地是要和注解搭配在某些方法上加上自定义注解然后要对这些方法进行增强(很少用execution指定哪些包下的哪些方法要增强)。那这时就要引出annotation、target、within了。我们一一讲解。
annotation 方法上是否有指定注解子类调用不重写的方法会被aop拦截调用重写的方法看是否加了指定注解。 首先引入依赖
dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-aop/artifactIdversion2.7.4/version
/dependencydependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-test/artifactIdversion2.7.4/versionscopetest/scope
/dependency自定义一个注解
import java.lang.annotation.Target;
import java.lang.annotation.*;Target({ElementType.METHOD, ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
Documented
public interface Outer {int limit() default 0;}目标类
import org.springframework.stereotype.Component;Component
public class Target {Outer(limit 8)public void invoke() {System.out.println(执行Target的方法);}}Component
public class SonTarget extends Target {}切面类
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;Component
Aspect
public class MyAspect {Around(annotation(com.gs.spring_boot_demo.aop.Outer))public Object around(ProceedingJoinPoint point) throws Throwable {Method method ((MethodSignature)point.getSignature()).getMethod();Outer outer method.getAnnotation(Outer.class);System.out.println(aop前置 outer.limit());return point.proceed();}}编写测试类
import org.springframework.boot.test.context.SpringBootTest;
import javax.annotation.Resource;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.jupiter.api.Test;SpringBootTest
public class AopTest {Resourceprivate Target target;Autowiredprivate SonTarget sonTarget;Testpublic void aop() {target.invoke();System.out.println(---);sonTarget.invoke();}}运行aop方法打印结果 把子类SonTarget修改一下
import org.springframework.stereotype.Component;Component
public class SonTarget extends Target {public void invoke() {System.out.println(子类执行Target的方法);}}再次运行测试类这时子类的invoke()方法不会被拦截了 当然如果SonTarget的invoke()方法上加上Outer那就能被aop拦截了。 target 调用方法的对象所属的类上是否有指定注解注解被Inherited修饰子类调用会生效无Inherited看子类上有无该注解。 自定义注解不动目标类修改为
import org.springframework.stereotype.Component;Component
Outer(limit 8)
public class Target {public void invoke() {System.out.println(执行Target的方法);}}import org.springframework.stereotype.Component;Component
public class SonTarget extends Target {public void invoke() {System.out.println(子类执行Target的方法);}}切面类修改为
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;Component
Aspect
public class MyAspect {/*** 要注意一下target很硬霸所有的bean都会被动态代理(不管类上有没有加自定* 义注解)所以要约束为本项目下的包下* 不然测试用例运行时会报错依赖中有些类是final的被动态代理会报错*/Around(target(com.gs.spring_boot_demo.aop.Outer) within(com.gs.spring_boot_demo..*))public void around(ProceedingJoinPoint point) throws Throwable {Method method ((MethodSignature)point.getSignature()).getMethod();Outer outer method.getDeclaringClass().getAnnotation(Outer.class);System.out.println(aop前置 outer.limit());point.proceed();}}测试类不动运行 SonTarget的invoke()没有被拦截想要被拦截就在SonTarget类上添加Outer或者自定义注解上增加Inherited(表明父类加上该注解后子类能够继承)
import java.lang.annotation.Target;
import java.lang.annotation.*;Target({ElementType.METHOD, ElementType.TYPE})
Retention(RetentionPolicy.RUNTIME)
Documented
Inherited
public interface Outer {int limit() default 0;}within 方法所属的类上是否有指定注解注解没有被Inherited修饰子类调用不重写的方法会被拦截调用重写的方法看子类上是否有注解注解被Inherited修饰子类调用方法都会被拦截不管是否重写 自定义注解改一下就把修饰它的Inherited去掉 目标类
import org.springframework.stereotype.Component;Component
Outer(limit 8)
public class Target {public void invoke() {System.out.println(执行Target的方法);}}import org.springframework.stereotype.Component;Component
public class SonTarget extends Target {}切面类修改为
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;Component
Aspect
public class MyAspect {Around(within(com.gs.spring_boot_demo.aop.Outer))public void around(ProceedingJoinPoint point) throws Throwable {Method method ((MethodSignature)point.getSignature()).getMethod();Outer outer method.getDeclaringClass().getAnnotation(Outer.class);System.out.println(aop前置 outer.limit());point.proceed();}}测试类不动运行 子类的方法能被拦截我们把子类的方法重写一下
import org.springframework.stereotype.Component;Component
public class SonTarget extends Target {public void invoke() {System.out.println(子类执行Target的方法);}}再次运行测试类打印出结果 子类的方法没有被拦截想要被拦截SonTarget类上加上Outer。 我们再试一下自定义注解被Inherited修饰的情况。Outer注解加上Inherited然后Target不动SonTarget也不动(重写了invoke()方法类上也没有Outer)运行测试类 SonTaget改一下不重写invoke()方法运行测试类