Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 391 Vote(s) - 3.59 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to set @Autowired constructor params as "required=false" individually

#1
I'm using the `@Autowired` annotation under a `@Configuration` class constructor.

@Configuration
public class MyConfiguration {

private MyServiceA myServiceA;
private MyServiceB myServiceB

@Autowired
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
}

As the [Spring documentation sais][1], I'm able to declare whether the annotated dependency is required.

If I mark the `@Autowired` annotation under the constructor as `required=false`, I'm saying that the two services to be autowired are not required *(as the Spring documentation says)*:


@Autowired(required = false)
public MyConfiguration(MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}

From Spring documentation:

> In the case of multiple argument methods, the 'required' parameter is
> applicable for all arguments.

How can I set the `required` attribute to each constructor parameter individually? Is necessary to use `@Autowired` annotation under every field?

Regards,

[1]:

[To see links please register here]

--
Reply

#2
If you're using Java 8 and Spring Framework 4, you can use `Optional`.

@Autowired
public MyConfiguration(Optional<MyServiceA> myServiceA, Optional<MyServiceB> myServiceB){
myServiceA.ifPresent(service->{this.myServiceA = service});
myServiceB.ifPresent(service->{this.myServiceB = service});
}
Reply

#3
**Explicit approach**

Basically, you have a bean which have some required and optional dependencies. The recommended way of handling this scenario, not only configuration beans but any other, is to create a constructor only for mandatory dependencies and use setter injection for optional ones.

public class MyConfiguration {

private final MyServiceA myServiceA;
private MyServiceB myServiceB

@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
}

@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = myServiceB;
}

}

With this approach you can easily unit test the class without necessity for any mocking library. You can create an object in testing state using the constructor and optional setters.

Putting `@Autowired(required = false)` directly on the field and removing the setter will also work, but since you are using the constructor injection, I assume you want to state dependencies more explicitly.

**Additional idea**

You can also consider using the Optional type to wrap not mandatory dependencies. It is common among developers to assume that if a class has a property, it should be set, which is obviously not right in your scenario. To mark the possibility of absence for particular dependencies more clear you probably can use Optional:

public class MyConfiguration {

private final MyServiceA myServiceA;
private Optional<MyServiceB> myServiceB

@Autowired
public MyConfiguration(MyServiceA myServiceA){
this.myServiceA = myServiceA;
this.myServiceB = Optional.empty();
}

@Autowired(required = false)
public void setMyServiceB(MyServiceB myServiceB) {
this.myServiceB = Optional.ofNullable(myServiceB);
}

}

Some people are against using the `Optional` type for class properties (mainly because of this [answer from Brian Goetz][1]), but at the end of the day it should be the decision made by the whole team that is going to work on the project.


[1]:

[To see links please register here]

Reply

#4
As of Spring Framework 5.0, you can also use a @Nullable annotation (of any kind in any package — for example, javax.annotation.Nullable from JSR-305):

@Configuration
public class MyConfiguration {

private MyServiceA myServiceA;
private MyServiceB myServiceB

@Autowired
public MyConfiguration(@Nullable MyServiceA myServiceA, MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}
}
Reply

#5
Since Spring 4.3.0.RC1 you can do this:

public MyConfiguration(MyServiceA myServiceA, @Autowired(required = false) MyServiceB myServiceB){
this.myServiceA = myServiceA;
this.myServiceB = myServiceB;
}

As `ElementType.PARAMETER` was added as annotation target.

From Spring 5.0 `@Autowired(required = false)` can also be replaced by `@Nullable` or a Kotlin nullable type can be used without any annotation, e.g. `MyServiceB?`
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through