问题
I have a runnable task where i am trying to Autowire field but when i do it the task doesn't run . When i Autowire the field outside the runnable it works fine . Why is this happening ? Also is there any other cleaner way to get new instances of a autowired field inside runnable other than Autowiring it inside ?
Here's my runnable method `
Runnable task = new Runnable() {
@Autowired
ICruxPanelClientService CruxPanelClientService;
public void run (){
CruxPanelClientService.setCruxWebServiceBaseURL("http://10.41.181.23:8080");
CronCruxModel m = new CronCruxModel();
m = model1.get(model_var);
System.out.println("EXECUTING");
System.out.println(m.getService_status() + " ---------EXEexecution");
System.out.println(m.getCat_name() + "Executing Name ");
// time = m.getService_time();
UpdateCategoryRequest updateCategoryRequest = new UpdateCategoryRequest();
CategoryModel categoryModel = new CategoryModel();
categoryModel.setColor(m.getCat_color());
categoryModel.setIcon(m.getCat_icon());
categoryModel.setIconWhite(m.getCat_icon_white());
categoryModel.setName(m.getCat_name());
categoryModel.setId(m.getCat_id());
categoryModel.setKey(m.getCat_catkey());
categoryModel.setIndexOrder(m.getCat_indexOrder());
updateCategoryRequest.setCategory(categoryModel);
CruxPanelClientService.updateCategory(updateCategoryRequest);
GetServiceDataIdByCategoryIdRequest request1 = new GetServiceDataIdByCategoryIdRequest();
request1.setId(m.getCat_id());
GetServiceDataIdByCategoryIdResponse response1 = CruxPanelClientService.getServiceDataIdByCategoryId(request1);
ArrayList<ServiceModel> service = new ArrayList<ServiceModel>();
service = response1.getServiceModels();
JSONArray json = new JSONArray();
if(m.getService_order_succ_msg()==null)
{
json = new JSONArray();
}
else {
json = new JSONArray(m.getService_order_succ_msg());
}
String message = m.getService_order_succ_msg();
for (int j=0;j<service.size();j++)
{
UpdateServiceMasterRequest req = new UpdateServiceMasterRequest();
ServiceModel s = new ServiceModel();
s=service.get(j);
;
JSONObject obj = new JSONObject();
if(json.length()==0 )
{
String ms = null;
s.setOrderSuccessMessage(ms);
req.setServiceModel(s);
}
else {
String message1 = json.get(j).toString();
if(message1.equals(null) || message1.equals("")) {
String ms = null;
s.setOrderSuccessMessage(ms);
req.setServiceModel(s);
}
else {
s.setOrderSuccessMessage(message1);
req.setServiceModel(s);
}
}
CruxPanelClientService.updateServiceMaster(req);
}
m.setService_status("executed");
UpdateCronCruxRequest q = new UpdateCronCruxRequest();
q.setCronCruxModel(m);
CruxPanelClientService.updateCronCrux(q);
}
};`
回答1:
The problem is spring doesn't control creation of your runnable. There are couple possible solutions:
- Put you runnable creation in some service, repository, controller, component or what ever handled by spring:
Example:
@Service
public class SomeService {
@Autowired
private ICruxPanelClientService cruxPanelClientService;
public Runnable newRunnable() {
return new Runnable() {
public void run() {
cruxPanelClientService <- will be visible here and injected
}
}
}
}
- Create runnable as bean with prototype scope
Example:
@Configuration
public class Runnableconfiguration {
@Bean
@Scope("prototype")
public Runnable newRunnbale(final ICruxPanelClientService cruxPanelClientService) {
return new Runnable() {
public void run() {
cruxPanelClientService <- will be visible here
}
}
}
}
回答2:
@Autowire
can't be used for anonymous classes (because you call new
, not Spring), you can autowire a field in outer class and then use that field inside your Runnable
.
Or make the Runnable
a full blown class (not anonymous) and make it a bean (and autowire, e.g. using the id
)
回答3:
Spring does not @autowire
anything into unmanaged instances (instances you create with new
, in contrast to instances created and managed by Spring).
This leaves you following options:
@autowire
the dependency outside and pass it to theRunnable
(or make it accessible to theRunnable
).- create a new class subclassing
Runnable
, and@autowire
it where you need it. - Instead of having the dependency injected, look it up (
applicationContext.getBean(..)
) when needing it.
Be careful with scopes and lazy initialization when using Threads, as some of the Spring scopes (e.g. "request" or "session" scope) are thread-local bound (e.g. when using a lazy request-scoped dependency in a new Thread, which when executed is no longer associated with the current request).
来源:https://stackoverflow.com/questions/38026330/autowired-not-working-inside-a-runnable