クラスを取得して呼び出す方法を反射することで@Autowired注入が無効になるソリューション
3567 ワード
引用する
最近、同社のプラットフォームプロジェクトを最適化しているが、このプラットフォームはto Bの性質であるため、コードを向上させ、より柔軟にするためにカスタマイズ開発する必要があるため、反射が用いられているが、使用中に@Autowiredの失効問題に遭遇した.
問題解決:
実際にこの問題が発生した原因は簡単ですが、取得したクラスがspringコンテナ管理に組み込まれていないため、エラーコードを見てみましょう.
反射コードは次のとおりです.
反射によってクラスを取得する方法の一部のコード:
上記のコードを実行すると、クラス内のcallBackメソッドは正常に取得できますが、debugがこのメソッドに入ると、@Autowiredで注入されたクラスが空であることがわかります.
反射中のコードを見ると、クラスを得る方法はclassです.新InstanceではSpringコンテナに関連付けられてbeanを取得する書き方はありませんが、クラスに@Autowiredというように注入されたオブジェクトがあれば空になります.
ソリューション:
エラーの原因を知っていれば、解決は簡単です.classを通過しないでください.新Instance方式で取得するのではなく、手動でspringコンテキストで取得すればこの問題を解決できます.修正後の反射コード
springコンテキストからクラスを手動で取得するコードが追加されました.
ツールクラスコードは次のとおりです.
小結
これで、この問題を解決しました.問題に遭遇したら、まず問題の原因を分析して、それから病状に応じて薬を飲んで、すぐに解決することができます.
最近、同社のプラットフォームプロジェクトを最適化しているが、このプラットフォームはto Bの性質であるため、コードを向上させ、より柔軟にするためにカスタマイズ開発する必要があるため、反射が用いられているが、使用中に@Autowiredの失効問題に遭遇した.
問題解決:
実際にこの問題が発生した原因は簡単ですが、取得したクラスがspringコンテナ管理に組み込まれていないため、エラーコードを見てみましょう.
反射コードは次のとおりです.
//
String className ="M1CallBackService";
Class c = Class.forName(packagePath + className);
Method m = c.getMethod("callBack", new Class[]{Integer.class});
//
Object[] arguments = new Object[]{new Integer(robotServiceInfo.getRobotId())};
m.invoke(c.newInstance(), arguments);
反射によってクラスを取得する方法の一部のコード:
@Autowired
private NativeSqlMapper nativeSqlMapper;
@Autowired
private EmailService emailService;
/**
* @Description:
* @author: zhenghao
* @date: 2019/12/13 14:56
*/
public void callBack(Integer robotId) {
String dateStr = DateUtils.getToDayYYYYMMDD();
List excelSheetModelList = new ArrayList<>();
//
List
上記のコードを実行すると、クラス内のcallBackメソッドは正常に取得できますが、debugがこのメソッドに入ると、@Autowiredで注入されたクラスが空であることがわかります.
反射中のコードを見ると、クラスを得る方法はclassです.新InstanceではSpringコンテナに関連付けられてbeanを取得する書き方はありませんが、クラスに@Autowiredというように注入されたオブジェクトがあれば空になります.
ソリューション:
エラーの原因を知っていれば、解決は簡単です.classを通過しないでください.新Instance方式で取得するのではなく、手動でspringコンテキストで取得すればこの問題を解決できます.修正後の反射コード
String className ="M1CallBackService";
Class c = Class.forName(packagePath + className);
Object obj = ApplicationContextHelper.popBean(c);
Method m = c.getMethod("callBack", new Class[]{Integer.class});
//
Object[] arguments = new Object[]{new Integer(robotServiceInfo.getRobotId())};
m.invoke(obj, arguments);
springコンテキストからクラスを手動で取得するコードが追加されました.
ツールクラスコードは次のとおりです.
package com.jack.common.utils.service;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
/**
* @Description: bean
* @author: zhenghao
* @date: 2019/12/14 12:04
*/
@Service
public class ApplicationContextHelper implements ApplicationContextAware {
private static ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext context) throws BeansException {
applicationContext = context;
}
/**
* bean
* @param clazz
* @param
* @return
*/
public static T popBean(Class clazz) {
//
if (applicationContext == null) {
return null;
}
return applicationContext.getBean(clazz);
}
public static T popBean(String name, Class clazz) {
if (applicationContext == null) {
return null;
}
return applicationContext.getBean(name, clazz);
}
}
小結
これで、この問題を解決しました.問題に遭遇したら、まず問題の原因を分析して、それから病状に応じて薬を飲んで、すぐに解決することができます.