@Autowired not working inside a runnable

匆匆过客 提交于 2020-01-24 05:42:17

问题


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:

  1. 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
            }
        }
    }

}
  1. 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 the Runnable (or make it accessible to the Runnable).
  • 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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!