问题描述
《深入浅出 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);
}
}
是不是版本不一致, 2.1以后的版本+只代表子类, 不算自身了