Suppose the bean is registered here.
@Configuration
public class configuration{
@Bean(name = "MyClass")
public MyClass getMyClass(@Value("avalue") final String s){
return new MyClass(s);
}
}
}
And the class has another class instantiated inside as below (No annotation needed for either?)
public class MyClass{
MyOtherClass myOtherClass;
public MyClass(String s){
this.myOtherClass = new MyOtherClass(s);
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
How this mechanic works? Is it safe to instantiate a new instance within a bean injection? What's the advantage or disadvantage of doing so?
If we were to avoid using it by making MyOtherClass a bean too, would this be the way? (Mainly concerning: is @Autowired and getMyclass() taking the right place or it's redundant?)
@Configuration
public class configuration{
@Bean(name = "MyOtherClass")
public MyOtherClass getMyOtherClass(@Value("avalue") final String s){
return new MyOtherClass(s);
}
}
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass){
//I was told the input should be myClass not myOtherClass,
//and the return is myClass not new MyClass(myOtherClass);
//since it's already autowired. Is that correct?
//What if the configuration.java and MyClass.java are in different project?
return myClass;
}
}
}
@Component
public class MyClass{
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
public class MyOtherClass{
String s;
public MyOtherClass(String s){
this.s = s;
}
}
If you want not to expose your MyOtherClass
and take control over creating its instances, you can use your first approach:
...
public MyClass(String s) {
this.myOtherClass = new MyOtherClass(s);
}
It is safe, but it is not a dependency injection: MyOtherClass
is not managed by Spring, so you won't be able to inject it in other beans using @Autowired
or to inject other spring managed classes into MyOtherClass
. Also, as mentioned by Andrew, it becomes impossible to mock MyOtherClass
.
If registering MyOtherClass
as a bean in a Spring context is fine, then the easiest way is to annotate both classes with @Component
and let Spring do its work (in this case you should use @ComponentScan
to help Spring auto-detect your classes):
@Component
class MyClass {
MyOtherClass myOtherClass;
@Autowired
public MyClass(MyOtherClass myOtherClass){
this.myOtherClass = myOtherClass;
}
}
@Component
class MyOtherClass {
String s;
public MyOtherClass(@Value("avalue") final String s){
this.s = s;
}
}
Or, using @Bean
(this will work if Config.java
and MyClass.java
are in different projects):
@Configuration
public class Config {
@Value("avalue")
private String s;
@Bean(name = "myClass")
public MyClass getMyClass(){
return new MyClass(getMyOtherClass());
}
@Bean(name = "myOtherClass")
public MyOtherClass getMyOtherClass() {
return new MyOtherClass(s);
}
}
Note: if you have already registered MyClass
in a Spring context using
@Component
public class MyClass {
...
}
then you don't need to do it again by
@Bean(name = "MyClass")
public MyClass getMyClass(MyClass myClass) {
return myClass;
}