背景

笔者目前做的项目中有许多根据前台传参,然后根据参数获取不同实现类,取执行不同的代码逻辑,代码类似如下:
下面展示一些。

现有实现

/*** 执行逻辑** @param type :  实现类类型* @return void* @author longwh  2020/11/9 - 13:55**/@GetMapping("/test")public void doSomething(String type){testFactory.getInstanse(type).Test("执行业务逻辑");}

其中testFactory是获取多实现的一个简单工厂,实现如下:
简单工厂

/*** @Author Longwenhao* @Date 2020/4/13 9:43* @Version 1.0**/
@Component
public class TestFactory {@Resourceprivate Map<String, TestService> testServices;public TestService getInstanse(String type){return testServices.get(type);}
}

但是因为本人很懒,不想通过工厂去获取具体的实现,想把这一步交给接口的调用者,所以在想将枚举注入spring中,然后前台传参直接获取到这个实现,直接调用实现的方法。

偷懒的小孩做法

因为想偷这一步懒,且最近笔者看了单例模式的最优实现是枚举,所以笔者打算尝试改造实现类:

改造后的实现枚举

/*** 测试枚举** @author longwh* @version 1.0, 2020/11/9 10:27*/
public enum TestServiceImpl implements TestService {/*** hello实现* @author longwh  2020/11/9 - 14:05**/HELLO{@Overridepublic String Test(String parement) {return "hello";}},/*** world实现* @author longwh  2020/11/9 - 14:05**/WORLD{@Overridepublic String Test(String parement) {return "world";}};
}

在配置中注入

/*** 枚举注入配置** @author longwh* @version 1.0, 2020/11/9 09:57*/
@Configuration
public class EnumConfig {@Beanpublic TestService getHello(){return TestServiceImpl.HELLO;}@Beanpublic TestService getWorld(){return TestServiceImpl.WORLD;}}

最后的controller实现长这样:

/*** 改造后的执行逻辑** @param type :  实现类类型* @return void* @author longwh  2020/11/9 - 13:55**/@GetMapping("/test")public void doSomething1(TestServiceImpl type){type.Test("执行业务逻辑");}

因为这里TestServiceImpl 是个枚举,其实接口调用者只需要传入一个字符串几个自动匹配到这个枚举实例,比如调用接口传入query参数为:HELLO,java回自动匹配到这个枚举下的HELLO实例,且java帮我们保证了单例。

执行结果

笔者改造完之后就兴冲冲的跑去运行代码了,然而结果却不尽如人意,如下:

Error creating bean with name 'testFactory': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getHello' defined in class path resource [com/example/demo/config/EnumConfig.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class com.example.demo.service.impl.TestServiceImpl$1: Common causes of this problem include using a final class or a non-visible class; nested exception is org.springframework.cglib.core.CodeGenerationException: java.lang.VerifyError-->Cannot inherit from final class

大概意思呢是spring无法创建testFactory这个bean。通过报错我们可以查看到是因为无法注入实现类导致的。

总结

但是这次尝试呢也不是毫无收获的,在找寻报错原因的过程中笔者对于spring的一些只是有有了一些深入的了解。

1.final类无法被CGLIB 代理:

因为枚举类的实例默认是static final修饰的,所以在放入spring容器中时候无法织入。为什么无法织入呢,因为放入spring容器中的实例其实并不是原来的对象,而是经过代理之后生成的代理对象,由于枚举是final修饰的,无法被继承,所以也就无法生成代理对象了。

2.这里是由于spring机制的原因导致无法织入,不代表笔者的思路有问题,目前笔者还没有想到可以避免这方面的方法,如果看到这篇文章的大佬提示一下实现思路,感激不尽!!

小孩的奇思妙想:将枚举注入到spring容器中相关推荐

  1. 解决无法注入spring容器,获取不到spring容器中的bean问题

    解决无法注入spring容器,获取不到spring容器中的bean问题 前两天工作中遇到一个问题,收到的需求是根据logbak日志实现通过过滤错误日志发送预警邮件到邮箱,logback自定义实现类如下 ...

  2. Spring Boot中普通类获取Spring容器中的Bean

    我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,自己动手n ...

  3. Spring容器中获取Bean实例的七种方式(附实战源码)

    目录 写作说明 一:写作原因 二:源码出处 实现方式 一:使用BeanFactory直接获取(不推荐) 二:在初始化时保存ApplicationContext对象 三:继承自抽象类Applicatio ...

  4. 【SpringBoot】在普通类中获取spring容器中的bean

    这段时间公司搞封闭开发,做一个联通总部的客服系统项目,是基于springboot的.在开发工程中遇到一个页面datagrid数据排序的功能,因为有多个表的数据都要用到排序功能,于是我就写了一个排序功能 ...

  5. 获取Spring容器中的实例

    1. 介绍 在Spring环境中想要获取一个类的实例,如果直接new出来,只是创建了一个新的对象并不是Spring容器中的实例,因此如果类中使用了@Value ,@Autowired等注解是不起作用的 ...

  6. spring boot获取spring容器中的bean对象

    我们知道如果我们要在一个类使用  spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接 ...

  7. Spring容器中获取 Bean 实例的七种方式

    点击关注公众号,利用碎片时间学习 说明 一.写作原因 首先解释一下写这篇博文的原因,因为在使用spring框架的过程中获取bean是非常常见的操作,但是网上非常的博文大多承自一家之言,因此很多可操作性 ...

  8. Servlet自动注入Spring容器中的Bean解决方法

    Servlet自动注入Spring容器中的Bean解决方法 参考文章: (1)Servlet自动注入Spring容器中的Bean解决方法 (2)https://www.cnblogs.com/jank ...

  9. java 从一个容器获取对象,Java 如何实现从spring容器中获取注入的bean对象

    Java 如何实现从spring容器中获取注入的bean对象 发布时间:2020-11-03 15:27:37 来源:亿速云 阅读:70 作者:Leah 这期内容当中小编将会给大家带来有关Java 如 ...

最新文章

  1. RobotFramework下的http接口自动化Set Request Body 关键字的使用
  2. 20家股东联名施压,要求贝佐斯停止向警方出售面部识别软件
  3. python使用笔记:pyautogui自动化控制鼠标和键盘
  4. C++ 默认参数和占位符
  5. Java关于equals()方法和“==”逻辑运算符的区别简介
  6. im4java profile_GraphicsMagick+im4java
  7. pcm 8k单声道和双声道采样_音频接口PCM
  8. python练手经典100例-Python练手项目实例汇总(附源码下载)
  9. 数据可视化工具的意义有哪些
  10. Linux 进程间通讯方式 pipe()函数
  11. html的meta标签的作用
  12. 【C++】类和对象(中) —— 构造函数 | 析构函数 | 拷贝构造 | 赋值运算符重载
  13. cmd命令把GHO转换成虚拟机可直接加载的硬盘格式实例
  14. PHP汉字取拼音缩写
  15. 《脱颖而出——成功网店经营之道》一2.6 连横:返利模式的应用及分销
  16. nod-1089-最长回文子串 V2
  17. 万万没想过,10年之后,游戏3D建模师逆袭了
  18. 一个命令行整理软著代码
  19. 成都短期计算机python培训
  20. 【基于uml高校新闻发布管理系统】

热门文章

  1. 名悦集团:手机导航VS汽车导航,哪种习惯用哪种
  2. 场景数据互为表里!畅想2027,保险行业发展愿景...
  3. flutter 支付宝支付
  4. HEVC intra和inter码率控制的不同
  5. 网络基础(二)之TCP/UDP协议
  6. 创业是一种心态、信念和坚持,是一种生活方式
  7. Linux系统开发 | 线程同步与互斥
  8. 金融贷款行业如何高效获客,积累意向客户群体——运营商大数据
  9. 23.(cesium篇)cesium城市建筑物光效
  10. CSDN 会员版块问题解决日志