The difference between @Configuration and @Componment
@Configuration
@Target({}) @Retention() @Documented @Component public @interface Configuration { @AliasFor( annotation = ) String value() default ""; }
public class Car { private int id; private String name; public int getId() { return id; } public void setId(int id) { = id; } public String getName() { return name; } public void setName(String name) { = name; } } public class Driver { private int id; private String name; private Car car; public int getId() { return id; } public void setId(int id) { = id; } public String getName() { return name; } public void setName(String name) { = name; } public Car getCar() { return car; } public void setCar(Car car) { = car; } } import ; import ; @Configuration public class MyTestConfig { @Bean public Driver driver() { Driver driver = new Driver(); (1); ("driver"); (car()); return driver; } @Bean public Car car() { Car car = new Car(); (1); ("car"); return car; } } import ; import ; @Component public class MyTestConfig { @Bean public Driver driver() { Driver driver = new Driver(); (1); ("driver"); (car()); return driver; } @Bean public Car car() { Car car = new Car(); (1); ("car"); return car; } }
The above two pieces of code are the same except for the different annotations on the MyTestConfig class, but Spring's handling of the two is completely different.
The first piece of code will work as we expected
Because the (car()) method in the code driver() will be executed by the Spring agent,
Spring finds that the bean requested by the method is already in the container, so it directly returns the bean in the container.
So there is only one instance of Car object in the global area.
The second piece of code is executing driver()
When (car()) is not proxyed by Spring, the car() method will be called directly to obtain a brand new Car object instance, so there will be multiple Car object instances globally.
The reasons for this difference are as follows:
In summary, all @Configuration with @Bean
The annotated methods will be dynamically proxied, so the same instance returned by calling this method.
It works: if the method is called for the first time, the original method will be executed and the result object will be registered in the Spring context, and then all calls to the method will only retrieve the object from the Spring context and return it to the caller.
In the second code above
(car()) is just a pure JAVA call. The method that is called multiple times returns different object instances.
To fix the problem in the second code, you can use @Autowired as follows:
import ; import ; import ; import ; //@Configuration @Component public class MyTestConfig2 { @Autowired Car car; @Bean public Driver driver() { Driver driver = new Driver(); (1); ("driver"); (car); return driver; } @Bean public Car car() { Car car = new Car(); (1); ("car"); return car; } }
Summarize
1. The class annotated via @Configuration or @Componment is non-lazy loading by default. You can use @Lazy or enable lazy loading on @Lazy on @Bean;
2. Class annotated by @Configuration will be dynamically proxyed by CGLIB by default. All methods marked by @Bean annotation will be called through proxy methods in the future. When using @Bean in this class, it is a single column;
3. Classes annotated through @Componment will not generate dynamic proxy by default. Using @Bean in this class is multi-instance.
The above is personal experience. I hope you can give you a reference and I hope you can support me more.