简体   繁体   中英

Spring DI with Constructor

I have the following code:

@Component
public class MainBean {

    @Autowired
    private MyTask myTask

    @Autowired
    private TaskScheduler taskScheduler


    public void start() {

        String str = "Print something to console";

        //somehow call constructor and pass str argument??
        taskScheduler.execute(myTask);

    }
}

@Component
public class MyTask implements Runnable {

    private String str;

    @Autowired
    public MyTask(String str) {
        this.str = str;
    }

    @Override
    public void run() {

        System.out.println(str);
    }
}

I want to call MyTask and pass the str argument to the constructor. How can I do this? I cant find any good examples anywhere.

If I understand correctly what you are trying to do, a good solution would be the following:

@Component
public class MainBean {

    @Autowired
    private MyTaskFactory myTaskFactory

    @Autowired
    private TaskScheduler taskScheduler


    public void start() {

        String str = "Print something to console";

        taskScheduler.execute(myTaskFactory.getTask(str));

    }
}


public class MyTaskFactory {

   public MyTask getTask(String str) {
       return new MyTask(str);
   }
}

@Configuration
public class MyTaskFactoryConfig {

   @Bean
   public MyTaskFactory myTaskFactory() {
      return new MyTaskFactory();
   }
}

Note that MyTask will then be changed to:

public class MyTask implements Runnable {

    private String str;

    public MyTask(String str) {
        this.str = str;
    }

    @Override
    public void run() {

        System.out.println(str);
    }
} 

As seen from annotations, you've configured MyTask to be Spring managed. Also, str property is Spring managed, it should be injected by Spring to MyTask .

So, whenever you need MyTask instance, you don't create it yourself.

You @Autowire wherever you need.

public class ClassThatNeedsMyTaskInstances{
    @Autowired
    MyTask myTask;
}

But beware that by default, MyTask will be a singleton, so you may want to change its scope to prototype .

But this may be a good case where you don't let Spring manage MyTask s lifecycle. Instead you manage it yourself by creating instances using new , or factory

The following examples are for injecting the string from and XML and a Java-based configuration:

XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="MyTaskConstructor" class="java.lang.String">
        <constructor-arg type="char[]" value="My value"></constructor-arg>
    </bean>
    <bean id="myTask" class="com.package.MyTask">
        <constructor-arg ref="MyTaskConstructor"/>
    </bean>
</beans>

Java-based

@Configuration
public class MyTaskConfig {

    @Bean
    public String getMyTaskConstructor() {
        return "My value";
    }

    @Bean
    public MyTask myTask() {
         return new MyTask(getMyTaskConstructor());
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM