Let's say I have a library (I cannot change it). There is a class Consumer that uses a spring component of class A.
#Component
public class Consumer{
#Autowired
private A a;
}
In my configuration class I want to define two beans of same class A depending on the profile.
#Configuration
public class Config {
#Bean
#Profile("!dev")
A a1(){
return new A();
}
#Bean
#Profile("dev")
A a2(){
return new A();
}
}
But when I start the app, I get next exception
Parameter 1 of constructor in sample.Consumer required a single bean, but 2 were found:
I can't get how to fix that. I've tried to create 2 separate configs for that with profile annotation and single bean there, but it also did not work.
Marking one bean #Primary also does not help.
Do you guys know how to fix that? Thanks!
UPD.
Let me make it more specific. That class is a part of dynamodb spring starter. Consumer - DynamoDBMapperFactory. My bean - DynamoDBMapperConfig. So I want to have 2 versions of DynamoDBMapperConfig in my app.
You need to stop scanning package where Consumer declared.
#Profile behaves differently if it's applied to the #Bean annotated method.
From Profile doc.:
Use distinct Java method names pointing to the same bean name if you'd like to define alternative beans with different profile conditions
This means, you should do:
#Configuration
public class Config {
#Bean("a")
#Profile("!dev")
A a1(){
return new A();
}
#Bean("a")
#Profile("dev")
A a2(){
return new A();
}
}
Note the same bean names.
Related
Spring 5, Java 8
I have multiple configuration files, one of the configuration file has #Autowire dependency. it does not complain on run time and works fine but intellij warns can't find those beans.
wondering if thats ok to have #Autowire or #Inject in configuration class.
why i have it is b/c its my websocket configuration and my handlers need dependencies.
It's OK.
#Configuration indicates that a class declares #Beans which might require dependencies. #Configuration itself is meta-annotated with #Component and "therefore may also take advantage of #Autowired/#Inject like any regular #Component".
I would recommend that you pass dependencies as method parameters rather than inject them into fields. It keeps the configuration class clear and emphasises the required dependencies for each #Bean method.
I prefer
class C {
#Bean
public A a(B b) { new A(b); }
}
to
class C {
private final B b;
#Bean
public A a() { new A(b); }
}
I have a Bean defined in a class decorated with #Configuration:
#Configuration
public class MyBeanConfig {
#Bean
public String configPath() {
return "../production/environment/path";
}
}
I have a class decorated with #TestConfiguration that should override this Bean:
#TestConfiguration
public class MyTestConfiguration {
#Bean
#Primary
public String configPath() {
return "/test/environment/path";
}
}
The configPath bean is used to set the path to an external file containing a registration code that must be read during startup. It is used in an #Component class:
#Component
public class MyParsingComponent {
private String CONFIG_PATH;
#Autowired
public void setCONFIG_PATH(String configPath) {
this.CONFIG_PATH = configPath;
}
}
While trying to debug this I set a breakpoint inside each method as well as the constructor of the test config class. The #TestConfiguration's constructor breakpoint is hit, so i know that my test configuration class instantiates, however the configPath method of that class is never hit. Instead, the configPath method of the normal #Configuration class is hit and the #Autowired String in MyParsingComponent is always ../production/environment/path rather than the expected /test/environment/path.
Not sure why this is happening. Any thoughts would be greatly appreciated.
As documented in the Detecting Test Configuration section of the Spring Boot reference manual, any beans configured in a top-level class annotated with #TestConfiguration will not be picked up via component scanning. So you have to explicitly register your #TestConfiguration class.
You can do that either via #Import(MyTestConfiguration.class) or #ContextConfiguration(classes = MyTestConfiguration.class) on your test class.
On the other hand, if your class annotated with #TestConfiguration were a static nested class within your test class, it would be registered automatically.
Make sure that the method name of your #Bean factory method does not match any existing bean name. I had issues with method names like config() or (in my case)
prometheusConfig() which collided with existing bean names. Spring skips those factory methods silently and simply does not call them / does not instantiate the beans.
If you want to override a bean definition in your test, use the bean name explicitly as string parameter in your #Bean("beanName") annotation.
Test configuration has to be explicitly imported in the test via #Import({MyTestConfiguration.class}).
The name of the #Bean methods in #Configuration and #TestConfiguration have to be different. At least it makes difference in Spring Boot v2.2.
Also make sure spring.main.allow-bean-definition-overriding=true otherwise the bean could not be overriden.
For me worked this code:
#TestConfiguration // 1. necessary
public class TestMessagesConfig {
#Bean
#Primary // 2. necessary
public MessageSource testMessageSource() { // 3. different method name than in production code e.g. add test prefix
}
}
I struggled with a related problem, whereby even though I was using an inner static class, my test bean was not being registered.
It turns out, You still need to add your inner static class to the #ContextConfiguration class array, otherwise the beans inside the #TestConfiguration doesn't get picked up.
public interface Foo {
String execute();
}
public class FooService {
private final Foo foo;
FooService(Foo foo) {
this.foo = foo;
}
public String execute() {
return foo.execute();
}
}
#ExtendWith(SpringExtension.class)
#ContextConfiguration(classes = {FooService.class, FooTest.FooTestConfig.class})
public class FooTest {
#Autowired
FooService fooService;
#Test
void test() {
Assertions.assertEquals("MY_TEST_BEAN", fooService.execute());
}
#TestConfiguration
static class FooTestConfig {
#Bean
public Foo getFooBean() {
return () -> "MY_TEST_BEAN";
}
}
}
I came across a similar issue recently and got it sorted out by annotating my testing bean with #Primary as well as #Bean. Not sure why it's required, which seems not documented in the Spring doc. The version of my SpringBoot is 2.0.3.
In my case it was an issue with #RunWith(SpringRunner.class), I'm not exactly sure why it wasn't working, I was following this - Testing in Spring Boot
But after replacing that with #ExtendWith(SpringExtension.class) the inner static #TestConfiguration class created the beans as expected.
Maybe a version mismatch - I'm using Spring Boot 2.7.2.
In my case replacing #Import(TestConfig.class) with #ContextConfiguration(classes=TestConfig.class) did the trick. For some reason, some of the beans from TestConfig but 1 wasn't until I replaced #Import with #ContextConfiguration.
This was also mentioned in some comments that were hidden because they had no upvotes.
I found it odd how several answers stated that the names of the #Beans have to be different from each other. How would that make one override the other?
There wasn't one specific answer that worked for me, but I've solved the issue by combining some of their advices.
Here's what worked for me.
Main configuration class:
#Configuration
public class SpringConfiguration {
#Bean
BeanInterface myBean() {
return new BeanImplementation();
}
#Bean
OtherClass otherBean() {
return new OtherClass();
}
}
Test configuration class:
#TestConfiguration
public class TestSpringConfiguration {
#Bean
#Primary
BeanInterface myBean() {
return new TestBeanImplementation();
}
}
Test class:
#SpringBootTest(classes = TestSpringConfiguration.class,
properties = "spring.main.allow-bean-definition-overriding=true")
public class Tests {
#Test
public void test() {
// do stuff
}
}
In this way, the "myBean" bean instance is the one defined in the TestSpringConfiguration class, while "otherBean" is the one defined in the SpringConfiguration class, since it's not overridden.
If I gave two different names to the "myBean" beans, the "real" one would still be initialized and, in my case, would give an error during tests, since it needs something that's only available at runtime in its proper environment.
Once I gave both the same name, Spring would throw an error saying that they were conflicting. Hence why I had to specify the property spring.main.allow-bean-definition-overriding=true in the #SpringBootTest annotation of the test class.
By the way, if you're NOT using Spring Boot, I guess these alternative annotations could work for you:
#ExtendWith(value = SpringExtension.class)
#ContextConfiguration(loader = AnnotationConfigContextLoader.class, // <- not sure about this one
classes = { SpringConfiguration.class, TestSpringConfiguration.class })
public class Tests {
#Test
public void test() {
// do stuff
}
}
Then, you would still have to set the property spring.main.allow-bean-definition-overriding=true in the test application.yml or application.properties file, or in some other way via code on startup.
Note: I'm not 100% sure that you would need the loader = AnnotationConfigContextLoader.class thing. Try without it, first. I needed it in a project of mine which had Spring without Boot, but I can't remember whether it's a standard thing to set or I needed it for some specific reason.
Why does this work:
#Configuration
public class MyConfig {
#Bean
public A getA() {
return new A();
}
#Bean // <-- Shouldn't I need #Autowired here?
public B getB(A a) {
return new B(a);
}
}
Thanks!
#Autowire lets you inject beans from context to "outside world" where outside world is your application.
Since with #Configuration classes you are within "context world ", there is no need to explicitly autowire (lookup bean from context).
Think of analogy like when accessing method from a given instance. While you are within the instance scope there is no need to write this to access instance method, but outside world would have to use instance reference.
Edit
When you write #Configuration class, you are specifying meta data for beans which will be created by IOC.
#Autowire annotation on the other hand lets you inject initialized beans, not meta-data, in application. So, there is no need for explicit injection because you are not working with Beans when inside Configuration class.
Hi Jan your question is marked as answered over 4 years ago but I've found a better source:
https://www.logicbig.com/tutorials/spring-framework/spring-core/javaconfig-methods-inter-dependency.html
here's another article with the same idea:
https://dzone.com/articles/spring-configuration-and, it also states that such usage is not well documented which I found true. (?)
so basically if beanA's initialization depends on beanB, spring will wire them without explicit #Autowired annotation as long as you declare these two beans in the application context (i.e. #Configuartion class).
A class with #Configuration annotation is where you're defining your beans for the context. But a spring bean should define its own dependencies. Four your case B class should be defining it's own dependencies in class definition. For example if your B class depends on your A class than it should be like below:
public class B
{
#Autowired
A aInstance;
public A getA()
{
return aInstance;
}
public void setA(A a)
{
this.aInstance = a;
}
}
In above case while spring is building its context it looks for the bean which's type is A which is also defined as a Bean at your configuration class and Autowires it to B at runtime so that B can use it when required.
I am studying for the Spring Core certification and I have some doubts related to the answer of this question founded on the study material stuff.
Why are you not allowed to annotate a final class with #Configuration
My reasoning is the following one for substantiate this assertion:
Consider the following configuration class:
#Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository();
}
#Bean
public TransferService transferService() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
#Bean
public AccountService accountService() {
return new AccountServiceImpl(accountRepository());
}
At first look this situation could appear strange because the first method (accountRepository()) instantiates an JdbcAccountRepository object as a bean having id=AccountRepository that, following the Spring default behavior, is a singleton
The second and the third method call twice more time the accountRepository() method that should instantiate twice more JdbcAccountRepository objects and this is not possibile because it is singleton !!!
So, to solve this situation Spring use the Inheritance-based Proxies strategy that expect to create a child class of my configuration class (the one annoted by #Configuration) and it is does:
For each bean, an instance is cached in the child class
Child class only calls super at first instantiation
So the child class is the entry point because the following behavior is implemented by this child class:
public class AppConfig$$EnhancerByCGLIB$ extends AppConfig {
public AccountRepository accountRepository() {
// if bean is in the applicationContext
// return bean
// else call super.accountRepository() and store bean in context
}
public TransferService transferService() {
// if bean is in the applicationContext, return bean
// else call super.transferService() and store bean in context
}
.....................................................
.....................................................
.....................................................
}
So if I annotate a configuration class with final Spring can't have this behavior because in Java a final class cannot be subclassed
Is it correct?
Using the same reasoning can I also assert that in Spring I can't have a final method annoted with #Bean annotation?
Because, as shown in the previous example, I have that when at startup time is created the child class (the proxy) of my configuration class happens that for each bean, an instance is cached in the child class and if it is final it is not possible (but I am absolutly not sure about this assertion)
Am I missing something? Can you give me the exact explaination?
Tnx
Spring creates dynamic proxies for classes annotated with #Configuration classes. Spring uses CGLIB to extend your class to create proxy. Hence, configuration classes cannot be final.
Regarding accountRepository() being invoked twice:
If you invoke accountRepository() method to create an instance, it is no more a Spring managed bean. Spring will not have any idea of the instances created in this manner. Hence, you will end up with multiple instances of JdbcAccountRepository
You can preserve the singleton behavior if you configure as below:
#Bean
public TransferService transferService(JdbcAccountRepository jdbcAcctRepo) {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(jdbcAcctRepo);
return service;
}
#Bean
public AccountService accountService(JdbcAccountRepository jdbcAcctRepo) {
return new AccountServiceImpl(jdbcAcctRepo);
}
I understand that #Component annotation was introduced in spring 2.5 in order to get rid of xml bean definition by using classpath scanning.
#Bean was introduced in spring 3.0 and can be used with #Configuration in order to fully get rid of xml file and use java config instead.
Would it have been possible to re-use the #Component annotation instead of introducing #Bean annotation? My understanding is that the final goal is to create beans in both cases.
#Component
Preferable for component scanning and automatic wiring.
When should you use #Bean?
Sometimes automatic configuration is not an option. When? Let's imagine that you want to wire components from 3rd-party libraries (you don't have the source code so you can't annotate its classes with #Component), so automatic configuration is not possible.
The #Bean annotation returns an object that spring should register as bean in application context. The body of the method bears the logic responsible for creating the instance.
#Component and #Bean do two quite different things, and shouldn't be confused.
#Component (and #Service and #Repository) are used to auto-detect and auto-configure beans using classpath scanning. There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach, since it's purely declarative.
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically as above. It decouples the declaration of the bean from the class definition, and lets you create and configure beans exactly how you choose.
To answer your question...
would it have been possible to re-use the #Component annotation instead of introducing #Bean annotation?
Sure, probably; but they chose not to, since the two are quite different. Spring's already confusing enough without muddying the waters further.
#Component auto detects and configures the beans using classpath scanning whereas #Bean explicitly declares a single bean, rather than letting Spring do it automatically.
#Component does not decouple the declaration of the bean from the class definition where as #Bean decouples the declaration of the bean from the class definition.
#Component is a class level annotation whereas #Bean is a method level annotation and name of the method serves as the bean name.
#Component need not to be used with the #Configuration annotation where as #Bean annotation has to be used within the class which is annotated with #Configuration.
We cannot create a bean of a class using #Component, if the class is outside spring container whereas we can create a bean of a class using #Bean even if the class is present outside the spring container.
#Component has different specializations like #Controller, #Repository and #Service whereas #Bean has no specializations.
Let's consider I want specific implementation depending on some dynamic state.
#Bean is perfect for that case.
#Bean
#Scope("prototype")
public SomeService someService() {
switch (state) {
case 1:
return new Impl1();
case 2:
return new Impl2();
case 3:
return new Impl3();
default:
return new Impl();
}
}
However there is no way to do that with #Component.
Both approaches aim to register target type in Spring container.
The difference is that #Bean is applicable to methods, whereas #Component is applicable to types.
Therefore when you use #Bean annotation you control instance creation logic in method's body (see example above). With #Component annotation you cannot.
I see a lot of answers and almost everywhere it's mentioned #Component is for autowiring where component is scanned, and #Bean is exactly declaring that bean to be used differently. Let me show how it's different.
#Bean
First it's a method level annotation.
Second you generally use it to configure beans in Java code (if you are not using xml configuration) and then call it from a class using the
ApplicationContext.getBean method. Example:
#Configuration
class MyConfiguration{
#Bean
public User getUser() {
return new User();
}
}
class User{
}
// Getting Bean
User user = applicationContext.getBean("getUser");
#Component
It is the general way to annotate a bean and not a specialized bean.
It is a class level annotation and is used to avoid all that configuration stuff through java or xml configuration.
We get something like this.
#Component
class User {
}
// to get Bean
#Autowired
User user;
That's it. It was just introduced to avoid all the configuration steps to instantiate and use that bean.
You can use #Bean to make an existing third-party class available to your Spring framework application context.
#Bean
public ViewResolver viewResolver() {
InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
viewResolver.setPrefix("/WEB-INF/view/");
viewResolver.setSuffix(".jsp");
return viewResolver;
}
By using the #Bean annotation, you can wrap a third-party class (it may not have #Component and it may not use Spring), as a Spring bean. And then once it is wrapped using #Bean, it is as a singleton object and available in your Spring framework application context. You can now easily share/reuse this bean in your app using dependency injection and #Autowired.
So think of the #Bean annotation is a wrapper/adapter for third-party classes. You want to make the third-party classes available to your Spring framework application context.
By using #Bean in the code above, I'm explicitly declare a single bean because inside of the method, I'm explicitly creating the object using the new keyword. I'm also manually calling setter methods of the given class. So I can change the value of the prefix field. So this manual work is referred to as explicit creation. If I use the #Component for the same class, the bean registered in the Spring container will have default value for the prefix field.
On the other hand, when we annotate a class with #Component, no need for us to manually use the new keyword. It is handled automatically by Spring.
When you use the #Component tag, it's the same as having a POJO (Plain Old Java Object) with a vanilla bean declaration method (annotated with #Bean). For example, the following method 1 and 2 will give the same result.
Method 1
#Component
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with a bean for 'theNumber':
#Bean
Integer theNumber(){
return new Integer(3456);
}
Method 2
//Note: no #Component tag
public class SomeClass {
private int number;
public SomeClass(Integer theNumber){
this.number = theNumber.intValue();
}
public int getNumber(){
return this.number;
}
}
with the beans for both:
#Bean
Integer theNumber(){
return new Integer(3456);
}
#Bean
SomeClass someClass(Integer theNumber){
return new SomeClass(theNumber);
}
Method 2 allows you to keep bean declarations together, it's a bit more flexible etc. You may even want to add another non-vanilla SomeClass bean like the following:
#Bean
SomeClass strawberryClass(){
return new SomeClass(new Integer(1));
}
You have two ways to generate beans.
One is to create a class with an annotation #Component.
The other is to create a method and annotate it with #Bean. For those classes containing method with #Bean should be annotated with #Configuration
Once you run your spring project, the class with a #ComponentScan annotation would scan every class with #Component on it, and restore the instance of this class to the Ioc Container. Another thing the #ComponentScan would do is running the methods with #Bean on it and restore the return object to the Ioc Container as a bean.
So when you need to decide which kind of beans you want to create depending upon current states, you need to use #Bean. You can write the logic and return the object you want.
Another thing worth to mention is the name of the method with #Bean is the default name of bean.
Difference between Bean and Component:
#component and its specializations(#Controller, #service, #repository) allow for auto-detection
using classpath scanning. If we see component class like #Controller, #service, #repository will be scan automatically by the spring framework using the component scan.
#Bean on the other hand can only be used to explicitly declare a single bean in a configuration class.
#Bean used to explicitly declare a single bean, rather than letting spring do it automatically. Its make septate declaration of bean from the class definition.
In short #Controller, #service, #repository are for auto-detection and #Bean to create seprate bean from class
- #Controller
public class LoginController
{ --code-- }
- #Configuration
public class AppConfig {
#Bean
public SessionFactory sessionFactory()
{--code-- }
Spring supports multiple types annotations such as #Component, #Service, #Repository. All theses can be found under the org.springframework.stereotype package.
#Bean can be found under the org.springframework.context.annotation package.
When classes in our application are annotated with any of the above mentioned annotation then during project startup spring scan(using #ComponentScan) each class and inject the instance of the classes to the IOC container. Another thing the #ComponentScan would do is running the methods with #Bean on it and restore the return object to the Ioc Container as a bean.
#Component
If we mark a class with #Component or one of the other Stereotype annotations these classes will be auto-detected using classpath scanning. As long as these classes are in under our base package or Spring is aware of another package to scan, a new bean will be created for each of these classes.
package com.beanvscomponent.controller;
import org.springframework.stereotype.Controller;
#Controller
public class HomeController {
public String home(){
return "Hello, World!";
}
}
There's an implicit one-to-one mapping between the annotated class and the bean (i.e. one bean per class). Control of wiring is quite limited with this approach since it's purely declarative. It is also important to note that the stereotype annotations are class level annotations.
#Bean
#Bean is used to explicitly declare a single bean, rather than letting Spring do it automatically like we did with #Controller. It decouples the declaration of the bean from the class definition and lets you create and configure beans exactly how you choose. With #Bean you aren't placing this annotation at the class level. If you tried to do that you would get an invalid type error. The #Bean documentation defines it as:
Indicates that a method produces a bean to be managed by the Spring container.
Typically, #Bean methods are declared within #Configuration classes.We have a user class that we needed to instantiate and then create a bean using that instance. This is where I said earlier that we have a little more control over how the bean is defined.
package com.beanvscomponent;
public class User {
private String first;
private String last;
public User(String first, String last) {
this.first = first;
this.last = last;
}
}
As i mentioned earlier #Bean methods should be declared within #Configuration classes.
package com.beanvscomponent;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
#Configuration
public class ApplicationConfig {
#Bean
public User superUser() {
return new User("Partho","Bappy");
}
}
The name of the method is actually going to be the name of our bean. If we pull up the /beans endpoint in the actuator we can see the bean defined.
{
"beans": "superUser",
"aliases": [],
"scope": "singleton",
"type": "com.beanvscomponent.User",
"resource": "class path resource
[com/beanvscomponent/ApplicationConfig.class]",
"dependencies": []
}
#Component vs #Bean
I hope that cleared up some things on when to use #Component and when to use #Bean. It can be a little confusing but as you start to write more applications it will become pretty natural.
#Bean was created to avoid coupling Spring and your business rules in compile time. It means you can reuse your business rules in other frameworks like PlayFramework or JEE.
Moreover, you have total control on how create beans, where it is not enough the default Spring instantation.
I wrote a post talking about it.
https://coderstower.com/2019/04/23/factory-methods-decoupling-ioc-container-abstraction/
1. About #Component
#Component functs similarily to #Configuration.
They both indicate that the annotated class has one or more beans need to be registered to Spring-IOC-Container.
The class annotated by #Component, we call it Component of Spring. It is a concept that contains several beans.
Component class needs to be auto-scanned by Spring for registering those beans of the component class.
2. About #Bean
#Bean is used to annotate the method of component-class(as mentioned above). It indicate the instance retured by the annotated method needs to be registered to Spring-IOC-Container.
3. Conclusion
The difference between them two is relatively obivious, they are used in different circumstances.
The general usage is:
// #Configuration is implemented by #Component
#Configuration
public ComponentClass {
#Bean
public FirstBean FirstBeanMethod() {
return new FirstBean();
}
#Bean
public SecondBean SecondBeanMethod() {
return new SecondBean();
}
}
Additional Points from above answers
Let’s say we got a module which is shared in multiple apps and it contains a few services. Not all are needed for each app.
If use #Component on those service classes and the component scan in the application,
we might end up detecting more beans than necessary
In this case, you either had to adjust the filtering of the component scan or provide the configuration that even the unused beans can run. Otherwise, the application context won’t start.
In this case, it is better to work with #Bean annotation and only instantiate those beans,
which are required individually in each app
So, essentially, use #Bean for adding third-party classes to the context. And #Component if it is just inside your single application.
#Bean can be scoped and #component cannot
such as
#Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)