Spring5 AOP编程:关于org.springframework.beans.factory.BeanNotOfRequiredTypeException报错

先上错误详细信息:

org.springframework.beans.factory.BeanNotOfRequiredTypeException: Bean named 'bookDaoImpl' is expected to be of type 'com.atguigu.dao.BookDaoImpl' but was actually of type 'com.sun.proxy.$Proxy19'

直译过来大概意思是说:这个叫做bookDaoImpl的Bean,应该是BookDaoImpl类型,然而现在是com.sun.proxy.$Proxy19类型

疑惑????查看对应源码:下图第七行报错!

    @Test
public void addTest() { // 在数据库中,添加 现代光电测试
// 1. Spring读取配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); // 2. 获取BookDaoImpl对象 (错误行)
BookDaoImpl bookDaoImpl = context.getBean("bookDaoImpl", BookDaoImpl.class); // 3. 测试方法
bookDaoImpl.add(new Book(18, "现代光电测试", 120, 4));
}

从这段代码上,bookDaoImpl确实应该是BookDaoImpl类型,按理说代码没写错,为啥getBean()方法返回的不是BookDaoImpl类型。直觉告诉我,应该是增强类代码出现问题,上增强类代码:

@Service // 创建对象
@Aspect // 这是一个代理对象
public class BookProxy { // 增强类 @Before(value = "execution(* com.atguigu.dao.BookDaoImpl.add(..))") // 注意参数 .. 别忘了
@Order(1)
public void addBefore() {
System.out.println("Proxy01:添加方法准备就绪!");
} @Before(value = "execution(* com.atguigu.dao.BookDaoImpl.add(..))")
@Order(2)
public void addBefore01() {
System.out.println("Proxy02:执行!");
}
}

检查代码之后,发现增强类也没问题啊............

没想明白

最后求助百度,发现有人说这个错误可能是因为JDK动态代理不支持类注入导致的

检查被增强类代码,发现确实如此,一切的源头:下图第六行代码,JdbcTemplate已经是一个类对象,使用JDK动态代理无法进行注入类对象的操作。

原增强类代码:

@Service(value = "bookDaoImpl")
public class BookDaoImpl implements BookDao{ // 注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate; // JDK动态代理并不能进行类的注入!! .......
}

因为JDK动态代理只支持创建接口实现类代理对象,从而增强类的方法。**

于是,解决方案如下:

新建一个被增强类,命名为BookServiceProxy:其中BookDao是接口,也就是原被增强类BookDaoImpl实现的接口。

解决方案的核心思想:通过一个类封装接口对象,并在这个类中的各个方法中,调用这个接口对应的方法,然后通过增强这个类的各个方法,从而达到 对 实现这个接口的类 的方法 的增强(有点绕,相当于套娃)。

至于为什么这么做?是因为JDK动态代理的原理,就是通过创建接口的另一个实现类,被将其作为代理对象,然后在类代理对象中,编写增强逻辑,从而对原实现类的方法进行增强。

@Service(value = "bookServiceProxy")
public class BookServiceProxy { // 注入BookDao
@Autowired
private BookDao bookDao; // 被增强类所实现的BookDao接口,因为是接口类型,能够进行注入! // add
public void addBook(Book book) { // Book 为 entity
bookDao.add(book);
} // update
public void updateBook(int classhours, String name) {
bookDao.update(classhours, name);
} // delete
public void deleteBook(String name) {
bookDao.delete(name);
}
}

重写编写增强类代码,对新的被增强类BookServiceProxy进行切面操作。

@Service // 创建对象
@Aspect // 这是一个代理对象
public class BookProxy { // 增强类 @Before(value = "execution(* com.atguigu.service.BookServiceProxy.addBook(..))") // 注意参数 .. 别忘了
@Order(1)
public void addBefore() {
System.out.println("Proxy01:添加方法准备就绪!");
} @Before(value = "execution(* com.atguigu.service.BookServiceProxy.addBook(..))")
@Order(2)
public void addBefore01() {
System.out.println("Proxy02:执行!");
}
}

测试代码:

    @Test
public void BookServiceProxyTest() {
// 1. Spring读取配置文件
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("config.xml"); // 2. 获取BookDaoImpl对象
BookServiceProxy bookServiceProxy = context.getBean("bookServiceProxy", BookServiceProxy.class); // 3. 测试方法
bookServiceProxy.addBook(new Book(18, "现代光电测试", 120, 4));
}

运行结果:

Proxy01:添加方法准备就绪!

Proxy02:执行!

10月 15, 2021 9:50:01 下午 com.alibaba.druid.support.logging.JakartaCommonsLoggingImpl info

信息: {dataSource-1} inited

插入操作执行成功!

Process finished with exit code 0

最新文章

  1. 【转】 iOS9.2-iOS9.3.3越狱插件清单
  2. 为什么document.firstChild找到的不是html节点
  3. MAC、IDFA、IMEI正则表达式
  4. 实验箱FPGA部分测试报告及A8与FPGA链接测试报告
  5. TelephonyManager对黑名单的管理
  6. 基本的Web控件二
  7. [改善Java代码]使用valueOf前必须进行校验
  8. LSJ_NHibernate第二章 ManagerPage
  9. Android开发--WIFI实现
  10. iOS LBS相关: 定位和中国特色的位置偏移纠正
  11. Trie - leetcode [字典树/前缀树]
  12. android 检测是否插入U盘方法之一
  13. spring jdbctemplate调用存储过程,返回list对象
  14. POJ 2187 - Beauty Contest - [凸包+旋转卡壳法][凸包的直径]
  15. cetus系列~ 继续分析
  16. python搭建简单http文件服务器
  17. TCP是如何实现三次握手的?
  18. SJA1000 CAN驱动程序演示实验
  19. EF Core中如何取消跟踪DbContext中所有被跟踪的实体
  20. vue中的minix

热门文章

  1. C#使用Thrift作为RPC框架入门(三)之三层架构
  2. [SQL]master..sysprocesses
  3. ICCV2021 | Swin Transformer: 使用移位窗口的分层视觉Transformer
  4. Codeforces Gym 101480C - Cow Confinement(扫描线+线段树)
  5. [linux] 大批量删除任务
  6. nginx_rewrite
  7. python(3)跳过第一行(多行)读入数据
  8. 02 Windows安装C语言开发工具CodeBlocks
  9. 第三个基础框架 — springMVC — 更新完毕
  10. javaWeb - 3 — JSP (技术已淘汰)— 更新完毕