SpringBoot的@DeclareParents注解引入功能,“+”号会导致异常,求解

新手上路,请多包涵

问题描述

《深入浅出 Spring Boot 2.x》书中案例源码中发现的一个问题,这个问题似乎没有引起太多人注意,查了一通啥都没有。所以在这提个问题,看有没有了解情况的大佬,帮忙解惑下,感激不尽!即:在 SpringBoot项目中使用@DeclareParents注解向Service类引入新接口中的功能时,value值结尾的“+”符号,会必定产生异常,已知2.0.0版本和2.1.3版本的SpringBoot一定会产生。没有尝试XML配置AOP引入,不知道XML配置是否也会出这个异常。

存在“+”号时报的异常:

Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'jacksonCodecCustomizer' defined in class path resource [org/springframework/boot/autoconfigure/http/codec/CodecsAutoConfiguration$JacksonCodecConfiguration.class]: Initialization of bean failed; nested exception is org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type org.springframework.boot.autoconfigure.http.codec.CodecsAutoConfiguration$JacksonCodecConfiguration$$Lambda$269.1506703662

问题出现的环境背景及自己尝试过哪些方法

环境:

  • 系统环境:win10
  • IDE:Eclipse

尝试过:

  • 修改案例源码中的value值由service实现类改为其接口,但“+”号没改 (报同样异常)
  • 修改value为接口并去除“+”号,会在收到URL请求时出异常
  • 直接去除案例源码中value末尾的“+”号直接使用service实现类,不会产生异常

相关代码

pojo类:

package com.springboot.chapter4.pojo;

public class User {
    private Long id;
    private String username;
    private String note;
    
    /* setter & getter 省略 */
}

aspect类:


package com.springboot.chapter4.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.DeclareParents;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

import com.springboot.chapter4.aspect.validator.UserValidator;
import com.springboot.chapter4.aspect.validator.impl.UserValidatorImpl;

@Aspect
@Component
public class MyAspect {
    
    @DeclareParents(value= "com.springboot.chapter4.aspect.service.impl.UserServiceImpl+", defaultImpl=UserValidatorImpl.class)
    public UserValidator userValidator;
    
    @Pointcut("execution(* com.springboot.chapter4.aspect.service.impl.UserServiceImpl.printUser(..))")
    public void pointCut() {
    }
        @Before("pointCut()")
    public void before() {
        System.out.println("before ......");
    }
    
    @After("pointCut()")
    public void after() {
        System.out.println("after ......");
    }
            
    @AfterReturning("pointCut()")
    public void afterReturning() {
        System.out.println("afterReturning ......");
    }
    
    @AfterThrowing("pointCut()")
    public void afterThrowing() {
        System.out.println("afterThrowing ......");
    }
        
    @Around("pointCut()")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("around before......");
        jp.proceed();
        System.out.println("around after......");
    }
}      

Controller类

package com.springboot.chapter4.aspect.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.springboot.chapter4.aspect.service.UserService;
import com.springboot.chapter4.aspect.validator.UserValidator;
import com.springboot.chapter4.pojo.User;

//定义控制器
@Controller
// 定义类请求路径
@RequestMapping("/user")
public class UserController {

    // 注入用户服务
    @Autowired
    private UserService userService = null;

    // 定义请求
    @RequestMapping("/print")
    // 返回json
    @ResponseBody
    public User printUser(Long id, String userName, String note) {
        User user = new User();
        user.setId(id);
        user.setUsername(userName);
        user.setNote(note);
        userService.printUser(user);
        return user;
    }

    // 定义请求
    @RequestMapping("/vp")
    // 返回json
    @ResponseBody
    public User validateAndPrint(Long id, String userName, String note) {
        User user = new User();
        user.setId(id);
        user.setUsername(userName);
        user.setNote(note);
        // 强制转换
        UserValidator userValidator = (UserValidator) userService;
        // 验证用户是否为空
        if (userValidator.validate(user)) {
            userService.printUser(user);
        }
        return user;
    }
}

Service接口

package com.springboot.chapter4.aspect.service;

import com.springboot.chapter4.pojo.User;

public interface UserService {
    
    public void printUser();

    public void printUser(User user);
            
    public void manyAspects();
}

Service实现类

package com.springboot.chapter4.aspect.service.impl;

import org.springframework.stereotype.Service;

import com.springboot.chapter4.aspect.service.UserService;
import com.springboot.chapter4.pojo.User;

@Service
public class UserServiceImpl implements UserService {
    
    private User user = null;

    @Override
    public void printUser(User user) {
        if (user == null) {
            throw new RuntimeException("检查用户参数是否为空......");
        }
        System.out.print("id =" + user.getId());
        System.out.print("\tusername =" + user.getUsername());
        System.out.println("\tnote =" + user.getNote());
    }

    @Override
    public void manyAspects() {
        System.out.println("测试多个切面顺序");
    }

    @Override
    public void printUser() {
        if (user == null) {
            throw new RuntimeException("检查用户参数是否为空......");
        }
        System.out.print("id =" + user.getId());
        System.out.print("\tusername =" + user.getUsername());
        System.out.println("\tnote =" + user.getNote());
    }
    
    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }
    
}

新功能接口

package com.springboot.chapter4.aspect.validator;

import com.springboot.chapter4.pojo.User;

public interface UserValidator {
    
    public boolean validate(User user);
}

新功能实现类

package com.springboot.chapter4.aspect.validator.impl;

import com.springboot.chapter4.aspect.validator.UserValidator;
import com.springboot.chapter4.pojo.User;


public class UserValidatorImpl implements UserValidator {

    @Override
    public boolean validate(User user) {
        System.out.println("引入新的接口:"+ UserValidator.class.getSimpleName());
        return user != null;
    }
}

Aspect配置类

package com.springboot.chapter4.aspect.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

import com.springboot.chapter4.aspect.MyAspect;
import com.springboot.chapter4.aspect.service.impl.UserServiceImpl;

@Configuration  
//启动@AspectJ切面编程  
@EnableAspectJAutoProxy  
//定义扫描包  
@ComponentScan(basePackages = {"com.springboot.chapter4.aspect.*"}, basePackageClasses = UserServiceImpl.class)
public class AspectConfig {
    
    @Bean(name = "myAspect")
    public MyAspect initMyAspect() {
        return new MyAspect();
    }
}

SpringBoot启动类

package com.springboot.chapter4.main;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

//指定扫描包
@SpringBootApplication(scanBasePackages = { "com.springboot.chapter4.aspect" })
public class Chapter4Application {

    // 启动切面
    public static void main(String[] args) {
        SpringApplication.run(Chapter4Application.class, args);
    }
}
阅读 6.1k
6 个回答

是不是版本不一致, 2.1以后的版本+只代表子类, 不算自身了

新手上路,请多包涵

应该去掉+,+号代表该UserServiceImpl 类的所有子类,UserServiceImpl 没有子类。

新手上路,请多包涵

老哥你现在解决了吗,我也碰到一样的问题。。

新手上路,请多包涵

我也遇到了同样的问题,不太了解是怎么回事

新手上路,请多包涵

我也遇到遇到了同样的问题,感谢了

新手上路,请多包涵

我遇到的情况是,单独使用@DeclareParents带上加号是不会报错的,功能也是正常的,但到了书中第五章,配置数据源那个地方,启动就报错,去掉@DeclareParents或者value值去掉+就好了。springboot版本2.2.6

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏