Spring的@DeclareParents注解

介绍

作用: 
  用于给被增强的类提供新的方法。(实现新的接口)
属性:
  value:
    用于指定目标类型的表达式。当在全限定类名后面跟上+时,表示当前类
及其子类
  defaultImpl:
      指定提供方法或者字段的默认实现类。
使用场景:
  当我们已经完成了一个项目的某个阶段开发,此时需要对已完成的某个类加入一些新的方法,我们首先想到的是写一个接口,然后让这些需要方法的类实现此接口,但是如果目标类非常复杂,牵一发而动全身,改动的话可能非常麻烦。此时就可以使用此注解,然后建一个代理类,同时代理该类和目标类。

简介(在 AspectJ 中称为类型间声明)使方面可以声明建议对象实现给定的接口,并代表那些对象提供该接口的实现。

您可以使用@DeclareParentsComments 进行介绍。此注解用于声明匹配类型具有新的父代(因此而得名)。例如,在给定名为UsageTracked的接口和该接口名为DefaultUsageTracked的实现的情况下,以下方面声明服务接口的所有实现者也都实现UsageTracked接口(例如,通过 JMX 公开统计信息):

@Aspect
public class UsageTracking {

    @DeclareParents(value="com.xzy.myapp.service.*+", defaultImpl=DefaultUsageTracked.class)
    public static UsageTracked mixin;

    @Before("com.xyz.myapp.SystemArchitecture.businessService() && this(usageTracked)")
    public void recordUsage(UsageTracked usageTracked) {
        usageTracked.incrementUseCount();
    }

}

要实现的接口由带 Comments 的字段的类型确定。 @DeclareParents注解的value属性是 AspectJ 类型的模式。任何匹配类型的 bean 都实现UsageTracked接口。请注意,在前面示例的建议中,服务 Bean 可以直接用作UsageTracked接口的实现。如果以编程方式访问 bean,则应编写以下内容:

UsageTracked usageTracked = (UsageTracked) context.getBean("myService");

示例代码

/**
 * @author WGR
 * @create 2020/9/23 -- 13:33
 */
public class ValidateServiceImpl implements ValidateService {
    @Override
    public boolean checkUser(User user) {
        if(user.getNickname().contains("孙子")){
                return false;
          }
           return true;
    }
}

/**
 * @author WGR
 * @create 2020/9/23 -- 13:32
 */
public interface ValidateService {

    boolean checkUser(User user);
}

@Component
@Aspect//表明当前类是一个切面类
public class LogUtil {

    @DeclareParents(value = "com.dalianpai.spring5.aop.service.UserService+", defaultImpl = ValidateServiceImpl.class)
    public static ValidateService validateService;

    @Before(value = "execution(* com.dalianpai.spring5.aop.service.impl.*.*(..)) && args(user,id) && this(validateService)")
    public void beforePrintLogC(String id, User user, ValidateService validateService) {
        boolean check = validateService.checkUser(user);
        if (check) {
            System.out.println("执行打印日志的功能");
        } else {
            throw new IllegalStateException("名称非法");
        }
        System.out.println("前置通知增强了beforePrintLoga" + id + "," + user);
    }


}

image-20200923135111176

posted @ 2020-09-23 13:53  天宇轩-王  阅读(533)  评论(0编辑  收藏  举报