日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

单元测试 applicationinfomanager bean无法注入_你真的会用Spring吗?如何在单例Bean中注入原型Bean...

發布時間:2025/3/20 javascript 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 单元测试 applicationinfomanager bean无法注入_你真的会用Spring吗?如何在单例Bean中注入原型Bean... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

遇到什么問題

假設單例 BeanA 需要使用原型 BeanB(BeanB 可能是 BeanA 的一個屬性值)。可是容器僅創建一次單例 BeanA,因此只有一次機會來設置屬性 BeanB。

@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)@Servicepublic class OrderService {}@Servicepublic class UserService {@Autowiredprivate OrderService orderService;public OrderService getOrderService() {return orderService;}}@Configuration@ComponentScanpublic class Main {public static void main(String[] args) {AnnotationConfigApplicationContext context =new AnnotationConfigApplicationContext(Main.class);UserService userService = context.getBean(UserService.class);OrderService orderService = userService.getOrderService();OrderService orderService1 = userService.getOrderService();//tureSystem.out.println(orderService == orderService1);}}

如果直接使用@Autowired注入,容器僅創建一次單例UserService,因此只有一次機會來設置OrderService。

那么,如何在單例 Bean 中注入原型 Bean 呢?

解決方案 1:實現 ApplicationContextAware

第一種解決方案,可以讓UserService實現ApplicationContextAware接口,然后在每次需要使用原型 BeanOrderService時通過調用容器的getBean方法。

@Servicepublic class UserService implements ApplicationContextAware {private ApplicationContext context;public OrderService getOrderService() {return context.getBean(OrderService.class);}@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {context = applicationContext;}}

Spring 官方并不建議使用這種方式:

The preceding is not desirable, because the business code is aware of and coupled to the Spring Framework. Method Injection, a somewhat advanced feature of the Spring IoC container, lets you handle this use case cleanly.

前面的內容是不理想的,因為業務代碼知道并耦合到 Spring 框架。 方法注入是 Spring IoC 容器的一項高級功能,使您可以干凈地處理此用例。

解決方案 2:使用@Lookup,實現方法注入

@Lookup

先來看一下@Lookup源碼

@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)@Documentedpublic @interface Lookup {/** * This annotation attribute may suggest a target bean name to look up. * If not specified, the target bean will be resolved based on the * annotated method's return type declaration. */String value() default "";}

@Lookup默認是通過方法的返回類型聲明來解析目標 Bean,也可以通過 value 來指定需要查找的目標 BeanName

介紹

https://docs.spring.io/spring/docs/5.1.9.RELEASE/spring-framework-reference/core.html#beans-factory-lookup-method-injection

Lookup method injection is the ability of the container to override methods on container-managed beans and return the lookup result for another named bean in the container. The lookup typically involves a prototype bean, as in the scenario described in the preceding section. The Spring Framework implements this method injection by using bytecode generation from the CGLIB library to dynamically generate a subclass that overrides the method.

機器翻譯:查找方法注入是容器覆蓋容器管理的 Bean 上的方法并返回容器中另一個命名 Bean 的查找結果的能力。 查找通常涉及原型 bean,如上一節中所述。 Spring 框架通過使用從 CGLIB 庫生成字節碼來動態生成覆蓋該方法的子類來實現此方法注入。

使用限制

For this dynamic subclassing to work, the class that the Spring bean container subclasses cannot be final, and the method to be overridden cannot be final, either.

為了使此動態子類起作用,Spring Bean 容器子類的類也不能是 final,而要覆蓋的方法也不能是 final。

Unit-testing a class that has an abstract method requires you to subclass the class yourself and to supply a stub implementation of the abstract method.

對具有抽象方法的類進行單元測試需要您自己對該類進行子類化,并提供該抽象方法的存根實現。

A further key limitation is that lookup methods do not work with factory methods and in particular not with @Bean methods in configuration classes, since, in that case, the container is not in charge of creating the instance and therefore cannot create a runtime-generated subclass on the fly.

另一個關鍵限制是,查找方法不適用于工廠方法,尤其不適用于配置類中的@Bean 方法,因為在這種情況下,容器不負責創建實例,因此無法創建運行時生成的子類。

根據 Spring 官方文檔,我們可以知道:

  • 方法注入是通過 CGLIB 生成字節碼來動態生成覆蓋該方法的子類來實現此方法注入
  • 因為是用 CGLIB 來實現的,所以當前類和當前方法是不能為 final 的
  • Spring 中使用@Lookup來實現方法注入
  • 使用@Lookup 實現單例 Bean 中注入原型 Bean

    @Servicepublic abstract class UserService {@Lookuppublic abstract OrderService getOrderServiceUsingLookup();}

    雖然這個類是抽象的,但是還可以被實例化到 Spring 容器中,因為 Spring 會對當前類生成子類來實現方法注入。至于具體是怎么生成的增強對象,讀者可以自行 debug 源碼學習。

    UserService代理對象

    總結

    以上是生活随笔為你收集整理的单元测试 applicationinfomanager bean无法注入_你真的会用Spring吗?如何在单例Bean中注入原型Bean...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。