Minimize method injection parameters in SpringBoot 2

spring bean method arguments
spring bean call method with parameter
autowire bean with parameters
spring requestparam multiple parameters
spring boot inject
spring boot configuration
spring autowire method parameter
spring boot bean configuration

I'm relatively new to the Spring community and I have a question about reducing the number of method injection parameters.

Example

Config Class

@Configuration
public class CustomConfig {

    @Bean
    public Step readStep() {
        return new MyObject();
    }

    @Bean
    public Step validateStep() {
        return new MyObject();
    }

    @Bean
    public Step writeStep() {
        return new MyObject();
    }

}

Job Class

public class SomeJob {

    @Bean
    public Job someServiceMethod(@Qualifier("readStep" Step readStep, 
           @Qualifier("writeStep" Step writeStep,
           @Qualifier("validateStep" Step validateStep) {
              //Do something
    }
}

So I'm wondering if there is a way to reduce the number of method injection parameters to one. Example maybe injecting CustomConfig.java as a parameter vs each individual bean.

public class SomeJob {

    @Bean
    public Job someServiceMethod(CustomConfig config) {
        config.readStep//etc
        //Do something
    }
}

You can create @component with all required bean already injected. Name it like MyCustomJobCommonCOnfig and use it as one method parameter.

Spring @Configuration and Injecting Bean Dependencies as , One of the ways Spring recommends injecting inter-dependencies between For eg, had the bar bean been defined in a different @Configuration class , the way to inject the dependency I find the method parameter approach simpler here: 2. <id>JCenter</id>. 3. <url>https://jcenter.bintray.com</url>. 4. If the name of parameter is same as bean provider method (the factory method) name then the dependency is resolved by name. The bean provider method can provide a different name than the method name by using @Bean(name = ), the injection point method's parameter name should match in that case as well.

Just to provide a code example for Grigoriev Nick answer.

@Configuration
public class CustomConfig {

    //Create a component injecting required beans into it. 
    @Getter
    @Component
    @RequiredArgsConstructor
    public class JobConfig {
        private final Step readStep;
        private final Step validateStep;
        private final Step writeStep;
    }

    @Bean
    public Step readStep() {
        return new MyObject();
    }

    @Bean
    public Step validateStep() {
        return new MyObject();
    }

    @Bean
    public Step writeStep() {
        return new MyObject();
    }

}

public class SomeJob {

    //Inject comonent into method. 
    @Bean
    public Job someServiceMethod(JobConfig config) {
          Step read = config.getReadStep(),
               validate = config.getValidateStep(),
               write = config.getWriteStep();

    }
}

Spring Boot: Passing Parameters, Spring Boot made passing parameters easy with Java annotations. Let's take a look at how Then, we will use Param in the web service method's signature. @​GetMapping("/hello2") 2. <project xmlns="http://maven.apache.org/POM/4.0.0" Understanding Inversion of Control and Dependency Injection. Method Injection using lookup-method property Before start jumping into the topic, let me brief about the two important scopes in Spring and how that is working inside the spring container. Singleton scoped beans instances are created only once per container and they are re-used for the multiple requested.

You could use the AnnotationConfigApplicationContext.

Add a name for each bean in the CustomConfig:

@Bean(name="readStep")
    public Step readStep() {
        return new MyObject();
    }

Then simply instantiate a AnnotationConfigApplicationContext and use the register method which accepts a bean configuration class then use the getBean method to get individual beans.

public class SomeJob {

  @Bean
  public Job someServiceMethod() {
  AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();

  applicaionContext.register(CustomConfig.class);
  applicationContext.refresh();

  Step readStep = (Step) applicationContext.getBean("readStep");

  }
}

Spring Boot Reference Documentation, 2.3.2. Installing the Spring Boot CLI. Manual Installation; Installation with SDKMAN! Using Application Arguments; Testing with a mock environment; Testing with Use Dependency Injection in Hibernate Components; 9.9.9. As a result, enabling lazy initialization can reduce the time that it takes your application to start. The main appeal of Method Injection to me is as a way of getting rid of a container dependency I sometimes had to incur using Spring 1.0, and which will apply to any container that supports the concept of “non-singleton” or “prototype” objects.

Spring Framework Reference Documentation, Thus if you dependency-inject a prototype-scoped bean into a If you access scoped beans within Spring Web MVC, in effect, within a request that ability to autowire fields and multiple parameter methods, use the new regular Java call which helps to reduce subtle bugs that can be hard to  Method parameters annotated with @RequestParam are required by default. This means that if the parameter isn’t present in the request, we'll get an error: GET /api/foos HTTP/1.1 ----- 400 Bad Request Required String parameter 'id' is not present

Spring Boot Features, 2. Externalized Configuration. 2.1. Configuring Random Values; 2.2. As a result​, enabling lazy initialization can reduce the time that it takes your application to start. The constructor arguments passed to SpringApplication are configuration Using the @Value("${property}") annotation to inject configuration properties  At runtime, Spring will implement the method in the same way, with a couple of additional tricks. First, note that it can call a complex constructor as well as inject other Spring beans, allowing us to treat SchoolNotification a bit more like a Spring-aware method.

Playing around with Spring Bean Configuration, @Configuration public class AppWithInjectionConfig { @Autowired private MyBean myOtherBean; By specifying myBean in the method parameter Spring will search for a bean of a matching type if as children of the package containing the @SpringBootApplication . Application. 1. 2. 3. 4. 5 Show / hide this help menu  To get started, we'll first discuss how to declare constraints on method parameters and return values of methods. As mentioned before, we can use annotations from javax.validation.constraints, but we can also specify custom constraints (e. g. for custom constraints or cross-parameter constraints). 2.1. Single Parameter Constraints

Comments
  • From my point of view with Spring we can split project to small beans with one responsibility but you are trying to do something oposit. Strange why are you want to do it?
  • @Alexey Usharovsk I'm using spring batch where I have many jobs with a config class that has some shared beans across jobs. When I create my Job bean, I need to get those shared beans to my job configuration. The actual shared beans are Step's.
  • cleaned up my question a bit.
  • This seems close to what I'm looking for, could you provide a little sample code to demo this option?
  • Would I continue to use my CustomConfig with the Configuration annotation and create an additional class MyCustomjob with the Component annotation and just inject all my required beans into the component? Or can this be done in the configuration class using the Component annotation instead of the configuration annotation?
  • I mean you can create just one more bean/comoponent and inject there all bean that you want. You can create it as separate class in separate file or like one more method annothated bean with sub class in same file. It's no matter, do it as you feel convinient.
  • I keep forgetting about the bean concept in Spring. Thanks.
  • This appears to be more complex than what I'm already doing. Grigoriev Nick seems to think I could just use @Component and inject the component, so I'm hoping to see a little sample as for how to do that, but might be much simpler.
  • Just wanted to comment about the code that you've added as an answer, and i commented here because i cannot comment on other answers yet. You are instantiating the beans as objects, not spring beans, so you need to use @Autowired for each object in the JobConfig before you inject it, also make a separate class (not an inner class) for these beans just as Grigoriev Nick mentioned.
  • If I'm not mistaken RequiredArgsConstructor is handling the autowire automatically for me. I was under the understanding that lombok is using Constructor injection. The code appeared to be working in test without any issues. Would this still work if the autowire was not there?
  • I see. I didn't know about the RequiredArgsConstructor, it handles constructor wiring.
  • Yes, I like how it cleans up the code. With the exception of removing the inner class, do you have any other suggestions?