Spring4:没有默认构造函数的基于CGLIB的代理类

在Spring中,如果要代理的目标对象的类未实现任何接口,则将创建基于CGLIB的代理。 在Spring 4之前,基于CGLIB的代理类需要默认的构造函数。 这不是CGLIB库的限制,而是Spring本身。 幸运的是,从Spring 4开始,这不再是问题。 基于CGLIB的代理类不再需要默认的构造函数。 这如何影响您的代码? 让我们来看看。

依赖注入的惯用法之一是构造函数注入。 它通常在需要注入的依赖项时使用,并且在启动对象后不得更改。 在本文中,我不会讨论为什么和何时应该使用构造函数依赖项注入。 我假设您在代码中使用了这个习惯用法,或者您考虑使用它。 如果您有兴趣了解更多信息,请参见本文底部的资源部分。

不含豆的施工剂注射

具有以下协作者:

package pl.codeleak.services;import org.springframework.stereotype.Service;@Service
public class Collaborator {public String collaborate() {return "Collaborating";}
}

我们可以通过构造函数轻松注入它:

package pl.codeleak.services;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class SomeService {private final Collaborator collaborator;@Autowiredpublic SomeService(Collaborator collaborator) {this.collaborator = collaborator;}public String businessMethod() {return collaborator.collaborate();}}

您可能会注意到, CollaboratorService都没有接口,但是它们都不是代理候选者。 因此,此代码将在Spring 3和Spring 4上正常运行:

package pl.codeleak.services;import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import pl.codeleak.Configuration;import static org.assertj.core.api.Assertions.assertThat;@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = Configuration.class)
public class WiringTests {@Autowiredprivate SomeService someService;@Autowiredprivate Collaborator collaborator;@Testpublic void hasValidDependencies() {assertThat(someService).isNotNull().isExactlyInstanceOf(SomeService.class);assertThat(collaborator).isNotNull().isExactlyInstanceOf(Collaborator.class);assertThat(someService.businessMethod()).isEqualTo("Collaborating");}
}

代豆施工剂注射

在许多情况下,您的bean需要在运行时用AOP proxy进行修饰,例如,当您想将声明性事务与@Transactional注释一起使用时。 为了可视化,我创建了一个方面,将为SomeService所有方法提供建议。 在定义了以下方面之后, SomeService将成为代理的候选者:

package pl.codeleak.aspects;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class DummyAspect {@Before("within(pl.codeleak.services.SomeService)")public void before() {// do nothing}}

当我使用Spring 3.2.9重新运行测试时,出现以下异常:

Could not generate CGLIB subclass of class [class pl.codeleak.services.SomeService]: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Superclass has no null constructors but no arguments were given

可以通过为SomeService提供默认的,无参数的构造函数来简单地解决此问题,但这不是我想要做的-因为我还需要使依赖关系成为非最终的。

另一个解决方案是为SomeService提供接口。 但是,在很多情况下,您不需要创建接口。

更新到Spring 4可以立即解决该问题。 如文档所述:

基于CGLIB的代理类不再需要默认的构造函数。 通过objenesis库提供支持,该库以内联方式重新打包并作为Spring框架的一部分分发。 通过这种策略,不再为代理实例调用任何构造函数。

我创建的测试将失败,但可以看到为SomeService创建了CGLIB代理:

java.lang.AssertionError: 
Expecting:<pl.codeleak.services.SomeService@6a84a97d>
to be exactly an instance of:<pl.codeleak.services.SomeService>
but was an instance of:<pl.codeleak.services.SomeService$$EnhancerBySpringCGLIB$$55c3343b>

从测试中删除第一个断言后,它将运行得非常好。

资源资源

  • 如果您需要了解有关构造函数依赖注入的更多信息,请查看Petri Kainulainen撰写的这篇出色文章: http ://www.petrikainulainen.net/software-development/design/why-i-changed-my-mind-about 场注入 。
  • Spring4中的核心容器改进: http : //docs.spring.io/spring/docs/current/spring-framework-reference/html/new-in-4.0.html#_core_container_improvements
  • 您可能也有兴趣阅读有关Spring的其他文章: Spring 4:带有Java 8 Date-Time API的@DateTimeFormat和
    在Spring MVC应用程序中使用Bean Validation 1.1获得更好的错误消息

翻译自: https://www.javacodegeeks.com/2014/07/spring-4-cglib-based-proxy-classes-with-no-default-constructor.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/363462.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux里面i386 i686 i486 i586代表什么?是什么意思

URL:http://hi.baidu.com/software_one/blog/item/85c7ccedd70d6925acafd5e0.html 在linux里面&#xff0c;我们经常会遇到i386 i686 i486 I586 这些代码&#xff0c;例如查看内核版本&#xff1a; [rootlocalhost logs]# uname -a Linux localhost.localdomain 2.6.18-164.el5…

汇编语言學習

汇编语言 汇编语言(Assembly Language)是面向机器的程序设计语言.汇编语言是一种功能很强的程序设计语言,也是利用计算机所有硬件特性并能直接控制硬件的语言。汇编语言”作为一门语言&#xff0c;对应于高级语言的编译器&#xff0c;需要一个“汇编器”来把汇编语言原文件汇编…

HOW-TO:带有MySQL的JEE应用程序中具有集群功能的Quartz Scheduler

Quartz Scheduler是Java世界中最流行的调度库之一。 过去&#xff0c;我主要在Spring应用程序中使用Quartz。 最近&#xff0c;我一直在研究将在云中部署的JBoss 7.1.1上运行的JEE 6应用程序中的调度。 我考虑的一种选择是Quartz Scheduler&#xff0c;因为它提供了与数据库的集…

DevStack方式安装queens版openstack

最近在学习openstack,在安装阶段就遇到了很多问题&#xff0c;特把安装过程记录如下&#xff0c;经笔者验证能正确安装openstack。 说明&#xff1a;安装后即为中文版。 2019/01/29: 安装环境&#xff1a; 宿主&#xff1a; Ubuntu 16.04 xenial Hypervisor: kvm 虚拟机&#x…

dev c++ 报错[Error] ld returned 1 exit status 的解决办法

我是个C语言的初学者&#xff0c;在使用dev c 编译器时&#xff0c;遇到一个情况&#xff1a;程序是正确的&#xff0c;能够正常的编译和运行&#xff0c;但是运行一次之后再次运行之时就出现了 报错[Error] ld returned 1 exit status&#xff0c;出现这个问题的原因是&#x…

2008年12月答疑贴

有问题请在此贴跟贴回复&#xff0c;我亦会在此贴回复。 请不要到无关的帖子中跟帖 请尽量描述清楚你的问题和需要&#xff0c;我的理解能力不是很强&#xff0c;呵呵。 请您遵守以下规则&#xff1a; 提问内容中请不要出现 感叹号&#xff0c;跪求等字样。 请尽量不要称呼我为…

androidmanifest.xml权限中文说明

程序执行需要读取到安全敏感项必需在androidmanifest.xml中声明相关权限请求, 完整列表如下: android.permission.ACCESS_CHECKIN_PROPERTIES 允 许读写访问”properties”表在checkin数据库中&#xff0c;改值可以修改上传( Allows read/write access to the “properties” t…

C语言使用scanf()函数时,%c前面和后面分别加上空格后的结果

在使用scanf()读取输入的字符时&#xff0c;当转换说明为%c时&#xff0c;"%c"、" %c"、"%c " 这三种不同的写法&#xff0c;对数据读取的结果有什么影响吗&#xff0c;答案是肯定的&#xff0c;%c 加不加空格&#xff0c;空格在前还是在后&am…

Python -- 自动导入所需要的模块

try: import xlwtexcept ImportError as e:   import os   print(e)   os.system("pip install xlwt")转载于:https://www.cnblogs.com/xlx12138/p/10551894.html

借助Apache Hadoop大规模扩展Apache Solr实时实时索引

播客的第22集是与Patrick Hunt的谈话 我们讨论了Apache Solr&#xff08;上游&#xff09;中的新工作&#xff0c;使它可以在Apache Hadoop上工作。 Solr支持将其索引和事务日志文件写入和读取到HDFS分布式文件系统。 这不使用Hadoop Map-Reduce处理Solr数据&#xff0c;而是仅…

C语言,关于getchar()清空回车符的几点经验

最近被getchar()弄的有点糊涂&#xff0c;现在基本缕清了。 拿程序举个例子&#xff1a; #include<stdio.h> int main(void) {char ch1,ch2;printf("Iam testing *********.\n");printf("So hard! ***********\n");ch1getchar();printf("$$$$$…

面试中关于多线程同步,你必须要思考的问题

ReentrantLock的实现网上有很多文章了&#xff0c;本篇文章会简单介绍下其java层实现&#xff0c;重点放在分析竞争锁失败后如何阻塞线程。因篇幅有限&#xff0c;synchronized的内容将会放到下篇文章。 Java Lock的实现 ReentrantLock是jdk中常用的锁实现&#xff0c;其实现逻…

C语言学习,关于fflush 和setvbuf

最近学习C语言的时候&#xff0c;学到文件的输入和输出函数&#xff0c; 对fflush和setvbuf 一直很困惑&#xff0c;现在虽然没有解开&#xff0c;但是有了一点浅显的理解。 1、ffulsh 针对的是输出流&#xff0c;是将输出缓存中的数据推到指向的文件里。 2、如果想清空输入缓…

可怜的mysql

唉&#xff0c;今天刚看到新闻&#xff0c;mysql 5.1 GA 虽然正式发布&#xff0c;但是却有一堆bug。 连mysql的创始人自己都批评sun不应该在未修复重大bug的前提下发布mysql 5.1 GA. 可怜的mysql,可怜的sun转载于:https://www.cnblogs.com/nevernet/archive/2008/12/04/134726…

linux查看用户、创建用户、设置密码、修改用户、删除用户命令

查看用户 tail -1 /etc/passwd tail -1 /etc/shadow id alex echo 123 |passwd --stdin alex # 设置密码&#xff0c;不需要交互[rootlocalhost ~]# tail -l /etc/passwd rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin nfsnobody:x:65534:65534:Anonymous NFS …

c# 笔记 数据类型转换 数组 函数

1、数据类型的转换&#xff08;cast&#xff09;包括隐性转换和显性转换。 当目标类型一定能满足源类型转换后的要求的话就是隐性转换&#xff0c;不需要任何代码直接转换&#xff0c;如果目标类型不一定能满足源类 型转换后的要求的话就是显性转换&#xff0c;显性转换需要在要…

使用外星人进行测试:如何使用Arquillian测试JPA类型转换器

该帖子与 Aslak Knutsen &#xff08; aslakknutsen &#xff09;一起撰写。 JPA类型转换器为定义实体属性如何持久存储到数据库提供了一种简便的方法。 您可以使用它们来实现许多不同的功能&#xff0c;例如&#xff0c;如上一篇文章中所示&#xff1a;加密数据&#xff1a; …

关于 C语言的 按位取反 ~

1、相关概念&#xff1a; 不管是正整数 还是 负整数在计算机中都是以 补码的形式存在的&#xff1b; 取反&#xff1a;0变1&#xff0c;1变0 就叫做取反&#xff0c;取反 符号位也要改变&#xff1b; 反码&#xff1a;符号位不变&#xff0c;其他位置0变1&#xff0c;1变0&a…

英语句型之展现问题篇3

表达不确定的用词&#xff1a;May, seem, be likely to, possible, probably, perhaps, be said that, be said to...51. In my mind, the following factors/reasons/causes need to be taken into consideration我认为&#xff0c;我们需要考虑下列因素/原因&#xff1a;52. …

【noip模拟赛5】任务分配 降维dp

描述 现有n个任务,要交给A和B完成。每个任务给A或给B完成&#xff0c;所需的时间分别为ai和bi。问他们完成所有的任务至少要多少时间。 输入 第一行一个正整数n&#xff0c;表示有n个任务。接下来有n行&#xff0c;每行两个正整数ai&#xff0c;bi。 输出 一个数&#xff0c;他…