操作系統:Windows 10
編程語言:Java
使用SpringBoot,版本2.6.6
開發工具:IDEA
我是因為使用了別人的代碼,但又學藝不精出的錯。
當時的場景是我要做一個smtp服務器、pop3服務器加上一個網頁服務器,這三個全部放在同一個項目下。網頁的就是springboot的8080端口,smtp服務器用了netty框架監聽25端口,pop3服務器用了netty框架監聽110端口。網頁端通過controller調用service、mapper都是可以@Autowired的,但是smtp和pop3服務器的代碼使用@Autowired不起作用,執行到相應代碼就是空指針報錯。原因大概或許是這兩部分的代碼沒有被springboot管理起來罷,我也不清楚。然后就找了下面這些代碼。
代碼的功能是獲取springboot管理的Bean對象並以靜態變量保存起來,在任何代碼的地方都可以獲取到想要的Bean對象
使用方法大致就是:
UserMapper userMapper = SpringContextHolder.getBean(UserMapper.class);
User user = userMapper.selectByUserName(“user1”);
引用別人的代碼如下:
/** * 以靜態變量保存Spring ApplicationContext, 可在任何代碼任何地方任何時候中取出ApplicaitonContext. */ @Component @Lazy(false) public class SpringContextHolder implements ApplicationContextAware { private static ApplicationContext applicationContext; /** * 實現ApplicationContextAware接口的context注入函數, 將其存入靜態變量. */ @Override public void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; // NOSONAR } /** * 取得存儲在靜態變量中的ApplicationContext. */ public static ApplicationContext getApplicationContext() { checkApplicationContext(); return applicationContext; } /** * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); return (T) applicationContext.getBean(name); } /** * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型. */ @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); return applicationContext.getBean(clazz); } /** * 清除applicationContext靜態變量. */ public static void cleanApplicationContext() { applicationContext = null; } private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException( "applicationContext未注入,請在applicationContext.xml中定義SpringContextHolder"); } } }
如果正常工作的話本應是這樣的,不過后來編譯的時候就報錯了
報的錯就是:applicationContext未注入,請在applicationContext.xml中定義SpringContextHolder
原因就是setApplicationContext沒有被調用,導致applicationContext為空。然后我在網上找applicationContext.xml到底在哪,然后試了幾個方法都不行。最后找到一個直接的方法
參考文章:https://www.cnblogs.com/qq931399960/p/10184151.html
直接在啟動類里獲取到applicationContext
SpringContextHolder的代碼還可以更簡潔一些
/** * 以靜態變量保存Spring ApplicationContext, 可在任何代碼任何地方任何時候中取出ApplicaitonContext. */public class SpringContextHolder{ private static ApplicationContext applicationContext; /** * 實現ApplicationContextAware接口的context注入函數, 將其存入靜態變量. */ public static void setApplicationContext(ApplicationContext applicationContext) { SpringContextHolder.applicationContext = applicationContext; // NOSONAR } /** * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型. */ @SuppressWarnings("unchecked") public static <T> T getBean(String name) { checkApplicationContext(); return (T) applicationContext.getBean(name); } /** * 從靜態變量ApplicationContext中取得Bean, 自動轉型為所賦值對象的類型. */ @SuppressWarnings("unchecked") public static <T> T getBean(Class<T> clazz) { checkApplicationContext(); return applicationContext.getBean(clazz); } private static void checkApplicationContext() { if (applicationContext == null) { throw new IllegalStateException( "applicationContext未注入,請從啟動類main方法中通過SpringApplication.run方法獲取到的返回值設置給本類的applicationContext變量"); } } }
參考文章:https://www.cnblogs.com/qq931399960/p/10184151.html