一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java 反射調用Service導致Spring注入Dao失效的解決方案

java 反射調用Service導致Spring注入Dao失效的解決方案

2021-12-09 10:54羅羅諾亞F Java教程

這篇文章主要介紹了java 反射調用Service導致Spring注入Dao失效的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

java 反射調用Service導致Spring注入Dao失效

問題發生背景:

原本打算做一個xml配置文件,寫一個公用類然后根據讀取配置反射動態調用方法。執行過程中,發現service中的dao為null,經過調查由于使用反射,導致dao注入失敗。

1、錯誤方法:通過反射執行service的方法

?
1
2
3
4
5
6
String serviceClass = templateInfo.getService();//service執行類的名稱
String method = templateInfo.getMethod();//調用方法名
//根據反射執行保存操作
Class<?> classType = Class.forName(serviceClass);
Method m = classType.getDeclaredMethod(method,new Class[]{PageData.class});
m.invoke(classType.newInstance(),pd);

2、解決方法:通過獲取Spring容器取得對象

?
1
2
3
4
5
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方法第一個參數不能使用newInstance方法,否則Service中dao的注入失敗,dao為null

反射調用導致Spring特性失效

今天在項目中遇到一個由于Java反射調用Bean方法而導致Spring特性失效的問題,折騰了半天,現給出解決方案。

1、拋出問題

我要在控制器的某個方法中通過反射調用一個service的方法,但是這個方法已經被納入切面同時該方法也依賴于其他通過Spring自動注入的Bean實例,準備代碼如下:

1.1、編寫TestAspectController類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@RestController
public class TestAspectController {
    @GetMapping("/testAspect")
    public Object testAspect() throws NoSuchMethodException {
        try {
            //通過完整類名反射加載類
            Class cla = Class.forName("com.icypt.learn.service.TestAspectService");
            //取得類實例
            Object obj = cla.newInstance();
            //通過實例反射調用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、編寫ModuleService類

?
1
2
3
@Service
public class ModuleService {
}

1.3、編寫TestKey注解

?
1
2
3
4
5
6
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TestKey {
    String key() default "";
}

1.4、編寫TestAspectService

?
1
2
3
4
5
6
7
8
9
@Component
public class TestAspectService {
    @Autowired
    private ModuleService moduleService;
    @TestKey(key = "key")
    public void sayHello() {
        System.out.println("************--->************" + moduleService);
    }
}

1.5、編寫TestAspect切面

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@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*********");
    }
}

運行結果:

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

根據結果可以發現,切面沒有被執行,同時依賴注入的Bean也沒有獲得實例,其實原因很簡單,就是因為我們是手動通過反射獲得的Bean的實例,這種方式相當于我們new Bean(),此Bean的實例已完全脫離Spring容器,所以Spirng無法感知它的存在,那么如何解決呢?

2、解決問題

2.1、編寫SpringContextUtil類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Component
public class SpringContextUtil implements ApplicationContextAware {
      // Spring應用上下文環境 
    private static ApplicationContext applicationContext;
      /**
     * 實現ApplicationContextAware接口的回調方法,設置上下文環境
     
     * @param applicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) { 
        SpringContextUtil.applicationContext = applicationContext; 
    
      /**
     * @return ApplicationContext
     */
    public static ApplicationContext getApplicationContext() { 
        return applicationContext; 
    
      /**
     * 獲取對象
     
     * @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);
    }
}

此類的作用就是手動通過BeanId獲取Bean實例。

2.2、修改TestAspectController類

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@RestController
public class TestAspectController {
    @GetMapping("/testAspect")
    public Object testAspect() throws NoSuchMethodException {
        try {
            //通過完整類名反射加載類
            Class cla = Class.forName("com.icypt.learn.service.TestAspectService");
            //獲取首字母小寫類名
            String simpleName = cla.getSimpleName();
            String firstLowerName = simpleName.substring(0,1).toLowerCase()
 + simpleName.substring(1);
            //通過此方法去Spring容器中獲取Bean實例
            Object obj = SpringContextUtil.getBean(firstLowerName, cla);
            //通過實例反射調用sayHello方法
            obj.getClass().getDeclaredMethod("sayHello").invoke(obj);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return "ok";
    }
}

其他類保持不變,運行結果如下:

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*********

通過結果可以發現,注入的Bean已經獲得了實例同時切面也友好的執行,問題完美解決。解決問題核心思想就是我們通過Spring的反射機制獲得Bean的實例化對象,而后通過Java的反射機制攜帶該實例對象去處理業務,這樣就不會使Bean脫離Spring容器管理,當然也可以享有Spring的Bean所有擁有的特性。

以上為個人經驗,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/Tracycater/article/details/50778662

延伸 · 閱讀

精彩推薦
  • Java教程Java實現搶紅包功能

    Java實現搶紅包功能

    這篇文章主要為大家詳細介紹了Java實現搶紅包功能,采用多線程模擬多人同時搶紅包,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程升級IDEA后Lombok不能使用的解決方法

    升級IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級,尋思已經有好久沒有升過級了。升級完畢重啟之后,突然發現好多錯誤,本文就來介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程20個非常實用的Java程序代碼片段

    20個非常實用的Java程序代碼片段

    這篇文章主要為大家分享了20個非常實用的Java程序片段,對java開發項目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關于小米推送Java代碼,小編覺得內容挺不錯的,現在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧...

    富貴穩中求8032021-07-12
  • Java教程Java BufferWriter寫文件寫不進去或缺失數據的解決

    Java BufferWriter寫文件寫不進去或缺失數據的解決

    這篇文章主要介紹了Java BufferWriter寫文件寫不進去或缺失數據的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程xml與Java對象的轉換詳解

    xml與Java對象的轉換詳解

    這篇文章主要介紹了xml與Java對象的轉換詳解的相關資料,需要的朋友可以參考下...

    Java教程網2942020-09-17
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程Java8中Stream使用的一個注意事項

    Java8中Stream使用的一個注意事項

    最近在工作中發現了對于集合操作轉換的神器,java8新特性 stream,但在使用中遇到了一個非常重要的注意點,所以這篇文章主要給大家介紹了關于Java8中S...

    阿杜7482021-02-04
主站蜘蛛池模板: 慢慢娇淫 | 无人区在线观看免费视频国语 | 天码毛片一区二区三区入口 | 日本九九热 | 十大网站免费货源 | 精品视频99 | 被老外操 | 国产精品亚洲午夜不卡 | 色综合久久最新中文字幕 | 日本乱中文字幕系列在线观看 | 免费精品国产在线观看 | 国产精品毛片va一区二区三区 | a级片在线观看免费 | 欧美激情精品久久久久久不卡 | 色在线亚洲视频www 色欲麻豆国产福利精品 | 国产香蕉久久 | 亚洲成A人片在线观看中文L | 天天综合天天综合 | 91精品国产色综合久久 | 国产美女久久精品香蕉69 | 朝鲜美女免费一级毛片 | 国产一区二区免费不卡在线播放 | 高清在线观看免费入口 | 亚洲va韩国va欧美va天堂 | 视频在线观看大片 | mm131亚洲精品久久 | 婷婷久久综合 | 国内免费高清视频在线观看 | 大香线一本 | 精品视频免费在线观看 | 91成人啪国产啪永久地址 | 国产精品免费 | 国内精品一区视频在线播放 | 美女无内裤下部黄 | 亚洲国产成人综合 | 天使萌痴汉在线中文字幕 | 5x社区发源地最新地址 | 农村妇女野战bbxxx | 单亲乱l仑在线观看免费观看 | 丁香婷婷在线视频 | 色综合久久综精品 |