最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java 反射調(diào)用Service導(dǎo)致Spring注入Dao失效的解決方案

 更新時(shí)間:2021年08月30日 09:40:16   作者:羅羅諾亞F  
這篇文章主要介紹了java 反射調(diào)用Service導(dǎo)致Spring注入Dao失效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教

java 反射調(diào)用Service導(dǎo)致Spring注入Dao失效

問(wèn)題發(fā)生背景:

原本打算做一個(gè)xml配置文件,寫(xiě)一個(gè)公用類(lèi)然后根據(jù)讀取配置反射動(dòng)態(tài)調(diào)用方法。執(zhí)行過(guò)程中,發(fā)現(xiàn)service中的dao為null,經(jīng)過(guò)調(diào)查由于使用反射,導(dǎo)致dao注入失敗。

1、錯(cuò)誤方法:通過(guò)反射執(zhí)行service的方法

String serviceClass = templateInfo.getService();//service執(zhí)行類(lèi)的名稱(chēng)
String method = templateInfo.getMethod();//調(diào)用方法名
//根據(jù)反射執(zhí)行保存操作
Class<?> classType = Class.forName(serviceClass);
Method m = classType.getDeclaredMethod(method,new Class[]{PageData.class});
m.invoke(classType.newInstance(),pd);

2、解決方法:通過(guò)獲取Spring容器取得對(duì)象

WebApplicationContext wac = ContextLoader.getCurrentWebApplicationContext(); 
DivStattisTabService service = (DivStattisTabService) 
Class<?>  cls = wac.getBean("divstattistabService").getClass(); 
Method m = classType.getDeclaredMethod(method,new Class[]{PageData.class});
m.invoke(wac.getBean("divstattistabService"),pd);

注:m.invoke方法第一個(gè)參數(shù)不能使用newInstance方法,否則Service中dao的注入失敗,dao為null

反射調(diào)用導(dǎo)致Spring特性失效

今天在項(xiàng)目中遇到一個(gè)由于Java反射調(diào)用Bean方法而導(dǎo)致Spring特性失效的問(wèn)題,折騰了半天,現(xiàn)給出解決方案。

1、拋出問(wèn)題

我要在控制器的某個(gè)方法中通過(guò)反射調(diào)用一個(gè)service的方法,但是這個(gè)方法已經(jīng)被納入切面同時(shí)該方法也依賴(lài)于其他通過(guò)Spring自動(dòng)注入的Bean實(shí)例,準(zhǔn)備代碼如下:

1.1、編寫(xiě)TestAspectController類(lèi)

@RestController
public class TestAspectController {
    @GetMapping("/testAspect")
    public Object testAspect() throws NoSuchMethodException {
        try {
            //通過(guò)完整類(lèi)名反射加載類(lèi)
            Class cla = Class.forName("com.icypt.learn.service.TestAspectService");
            //取得類(lèi)實(shí)例
            Object obj = cla.newInstance();
            //通過(guò)實(shí)例反射調(diào)用sayHello方法
            obj.getClass().getDeclaredMethod("sayHello").invoke(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return "ok";
    }
}

1.2、編寫(xiě)ModuleService類(lèi)

 @Service
public class ModuleService {
}

1.3、編寫(xiě)TestKey注解

@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestKey {
    String key() default "";
}

1.4、編寫(xiě)TestAspectService

@Component
public class TestAspectService {
    @Autowired
    private ModuleService moduleService;
    @TestKey(key = "key")
    public void sayHello() {
        System.out.println("************--->************" + moduleService);
    }
}

1.5、編寫(xiě)TestAspect切面

@Aspect
@Component
public class TestAspect {
    @Pointcut("@annotation(com.icypt.learn.aspect.TestKey)")
    public void process() {
    }
    @Before("process()")
    public void boBefore() {
        System.out.println("********before*********");
    }
    @After("process()")
    public void doAfter() {
        System.out.println("********after*********");
    }
}

運(yùn)行結(jié)果:

2019-03-28 21:57:26.548 INFO 30348 --- [nio-8082-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-03-28 21:57:26.548 INFO 30348
--- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2019-03-28 21:57:26.587 INFO 30348
--- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 39 ms
************--->************null

根據(jù)結(jié)果可以發(fā)現(xiàn),切面沒(méi)有被執(zhí)行,同時(shí)依賴(lài)注入的Bean也沒(méi)有獲得實(shí)例,其實(shí)原因很簡(jiǎn)單,就是因?yàn)槲覀兪鞘謩?dòng)通過(guò)反射獲得的Bean的實(shí)例,這種方式相當(dāng)于我們new Bean(),此Bean的實(shí)例已完全脫離Spring容器,所以Spirng無(wú)法感知它的存在,那么如何解決呢?

2、解決問(wèn)題

2.1、編寫(xiě)SpringContextUtil類(lèi)

@Component
public class SpringContextUtil implements ApplicationContextAware {
      // Spring應(yīng)用上下文環(huán)境  
    private static ApplicationContext applicationContext;
      /** 
     * 實(shí)現(xiàn)ApplicationContextAware接口的回調(diào)方法,設(shè)置上下文環(huán)境 
     *  
     * @param applicationContext 
     */  
    public void setApplicationContext(ApplicationContext applicationContext) {  
        SpringContextUtil.applicationContext = applicationContext;  
    }  
      /** 
     * @return ApplicationContext 
     */  
    public static ApplicationContext getApplicationContext() {  
        return applicationContext;  
    }  
      /** 
     * 獲取對(duì)象 
     *  
     * @param name 
     * @return Object
     * @throws BeansException 
     */  
    public static Object getBean(String name) throws BeansException {
        return applicationContext.getBean(name);  
    }
    public static Object getBean(String name, Class cla) throws BeansException {
        return applicationContext.getBean(name, cla);
    }
}

此類(lèi)的作用就是手動(dòng)通過(guò)BeanId獲取Bean實(shí)例。

2.2、修改TestAspectController類(lèi)

@RestController
public class TestAspectController {
    @GetMapping("/testAspect")
    public Object testAspect() throws NoSuchMethodException {
        try {
            //通過(guò)完整類(lèi)名反射加載類(lèi)
            Class cla = Class.forName("com.icypt.learn.service.TestAspectService");
            //獲取首字母小寫(xiě)類(lèi)名
            String simpleName = cla.getSimpleName();
            String firstLowerName = simpleName.substring(0,1).toLowerCase()
 + simpleName.substring(1);
            //通過(guò)此方法去Spring容器中獲取Bean實(shí)例
            Object obj = SpringContextUtil.getBean(firstLowerName, cla);
            //通過(guò)實(shí)例反射調(diào)用sayHello方法
            obj.getClass().getDeclaredMethod("sayHello").invoke(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return "ok";
    }
}

其他類(lèi)保持不變,運(yùn)行結(jié)果如下:

2019-03-28 22:13:59.311 INFO 37252 --- [nio-8082-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring FrameworkServlet 'dispatcherServlet'
2019-03-28 22:13:59.312 INFO 37252
--- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization started 2019-03-28 22:13:59.350 INFO 37252
--- [nio-8082-exec-1] o.s.web.servlet.DispatcherServlet : FrameworkServlet 'dispatcherServlet': initialization completed in 38 ms
********before*********
************--->************com.icypt.learn.service.ModuleService@5681f667
********after*********

通過(guò)結(jié)果可以發(fā)現(xiàn),注入的Bean已經(jīng)獲得了實(shí)例同時(shí)切面也友好的執(zhí)行,問(wèn)題完美解決。解決問(wèn)題核心思想就是我們通過(guò)Spring的反射機(jī)制獲得Bean的實(shí)例化對(duì)象,而后通過(guò)Java的反射機(jī)制攜帶該實(shí)例對(duì)象去處理業(yè)務(wù),這樣就不會(huì)使Bean脫離Spring容器管理,當(dāng)然也可以享有Spring的Bean所有擁有的特性。

以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • Java使用位運(yùn)算實(shí)現(xiàn)權(quán)限管理的示例詳解

    Java使用位運(yùn)算實(shí)現(xiàn)權(quán)限管理的示例詳解

    在開(kāi)發(fā)中,權(quán)限管理是一個(gè)非常常見(jiàn)的需求,本文將詳細(xì)講解如何使用 Java 中的 位運(yùn)算 實(shí)現(xiàn)一個(gè)輕量級(jí)、高效的權(quán)限管理系統(tǒng),并提供完整的代碼示例和解釋,感興趣的小伙伴可以了解下
    2025-06-06
  • Springboot項(xiàng)目使用AOP與自定義注解記錄請(qǐng)求日志方式

    Springboot項(xiàng)目使用AOP與自定義注解記錄請(qǐng)求日志方式

    這篇文章主要介紹了Springboot項(xiàng)目使用AOP與自定義注解記錄請(qǐng)求日志方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2025-06-06
  • Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例

    Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例

    本篇文章主要介紹了Java時(shí)間輪算法的實(shí)現(xiàn)代碼示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-08-08
  • Java 前臺(tái)加后臺(tái)精品圖書(shū)管理系統(tǒng)的實(shí)現(xiàn)

    Java 前臺(tái)加后臺(tái)精品圖書(shū)管理系統(tǒng)的實(shí)現(xiàn)

    相信每一個(gè)學(xué)生學(xué)編程的時(shí)候,應(yīng)該都會(huì)寫(xiě)一個(gè)小項(xiàng)目——圖書(shū)管理系統(tǒng)。為什么這么說(shuō)呢?我認(rèn)為一個(gè)學(xué)校的氛圍很大一部分可以從圖書(shū)館的氛圍看出來(lái),而圖書(shū)管理系統(tǒng)這個(gè)不大不小的項(xiàng)目,接觸的多,也比較熟悉,不會(huì)有陌生感,能夠練手,又有些難度,所以我的小項(xiàng)目也來(lái)了
    2021-11-11
  • SpringBoot項(xiàng)目POM文件的使用小結(jié)

    SpringBoot項(xiàng)目POM文件的使用小結(jié)

    本文主要詳細(xì)介紹了Maven中SpringBoot項(xiàng)目的POM文件配置,包括項(xiàng)目的依賴(lài)和插件,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2024-11-11
  • java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件

    java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件

    這篇文章主要為大家詳細(xì)介紹了java使用Socket實(shí)現(xiàn)SMTP協(xié)議發(fā)送郵件的相關(guān)資料,感興趣的小伙伴們可以參考一下
    2016-05-05
  • Java微服務(wù)架構(gòu)中的關(guān)鍵技術(shù)和設(shè)計(jì)原則解讀

    Java微服務(wù)架構(gòu)中的關(guān)鍵技術(shù)和設(shè)計(jì)原則解讀

    Java是一種面向?qū)ο蟮母呒?jí)編程語(yǔ)言,具有跨平臺(tái)兼容性、自動(dòng)內(nèi)存管理等特點(diǎn),它支持多線程、異常處理,并擁有豐富的標(biāo)準(zhǔn)庫(kù)和強(qiáng)大的社區(qū)生態(tài),微服務(wù)架構(gòu)是將應(yīng)用分解為多個(gè)小型服務(wù)的設(shè)計(jì)風(fēng)格
    2024-11-11
  • java使用UDP實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)通信

    java使用UDP實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)通信

    這篇文章主要為大家詳細(xì)介紹了java使用UDP實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)通信,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • JavaPoet的使用指南小結(jié)

    JavaPoet的使用指南小結(jié)

    這篇文章主要介紹了JavaPoet的使用指南小結(jié),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • Spring Boot Security 結(jié)合 JWT 實(shí)現(xiàn)無(wú)狀態(tài)的分布式API接口

    Spring Boot Security 結(jié)合 JWT 實(shí)現(xiàn)無(wú)狀態(tài)的分布式API接口

    JSON Web Token(縮寫(xiě) JWT)是目前最流行的跨域認(rèn)證解決方案。這篇文章主要介紹了Spring Boot Security 結(jié)合 JWT 實(shí)現(xiàn)無(wú)狀態(tài)的分布式API接口 ,需要的朋友可以參考下
    2019-04-04

最新評(píng)論

福州市| 山东| 华亭县| 潞城市| 闽侯县| 河北区| 开远市| 东辽县| 耿马| 株洲县| 海伦市| 霍山县| 四会市| 阳高县| 密云县| 扬中市| 大安市| 双辽市| 长春市| 鄂尔多斯市| 都江堰市| 平邑县| 灵台县| 阿坝县| 北京市| 通海县| 屯门区| 清徐县| 五华县| 温州市| 华阴市| 棋牌| 田东县| 山东省| 峡江县| 涡阳县| 雅安市| 泽州县| 大庆市| 西盟| 澄城县|