I am aware of calling #Bean annotated methods from within a #Configuration as already discussed.
But I don't understand why it doesn't work when the bean is overwritten.
I have a legacy class, which I can't modify. It's a configuration and a business bean at the same time. This is a simplified version:
#Configuration
public class MyBean {
String someMethod() {
return otherBean() + "|" + otherBean();
}
int called = 0;
#Bean
Object otherBean() {
return called ++;
}
}
Inside the someMethod() the factory method otherBean() is called two times and as far as annotated with #Bean the instance should be gotten from the Spring context and therefore should the actual code return called ++; be called only once. Expected output from the someMethod() should be always 0|0 and it is so indeed in the production.
Trouble comes when I am about to redefine the bean in a unit test:
#SpringJUnitConfig//(MyBean.class)
public class BeanTest {
#Autowired
MyBean myBean;
#Test
void testIt() {
assertEquals("0|0", myBean.someMethod());
}
#Configuration
static class TestConfig {
#Bean
MyBean myBean() {
return new MyBean();
}
}
}
The reason could be some additional settings of the MyBean instance in the test (not included in the snippet above).
Now, calling myBean.someMethod() returns 0|1 instead of 0|0.
Everything works again (result is 0|0), when the TestConfig configuration is removed and configuration of the test context is set as #SpringJUnitConfig(MyBean.class).
What's different in registering the bean in the test?
The "magic" of proxying method calls annotated with #Bean and returning instances from the Spring context happens only in configuration beans (like here: #SpringJUnitConfig(MyBean.class)).
But when you create a new instance as return new MyBean(), the #Configuration annotation is ignored and the object is registered as a normal bean (#Bean MyBean myBean()) but not a configuration. That's why the methods calls otherBean() create always a new instance.
Related
I am having one problem where bean definition for a single Service are defined in 2 different configuration classes.
#Configuration
public class ConfigurationA{
#Primary
#Bean("beana")
public beanA(){
return Mockito.mock(BeanA.class);
}
#Bean("beanb")
public beanB(){
return new BeanB(beanA());
}
#PostConstruct
public void initialize(){
beanA().dosomething();
}
}
#Configuration
public class ConfigurationB{
#Bean("beana")
public beanA(){
return new BeanA();
}
}
So when intialize() method is called, I am expecting mocked instance of BeanA will be used but its using real instance that is injected via ConfigurationB class.
I have marked "beana" as primary bean so spring should Ideally use this instance but its using the actual real instance defined in different configuration class.
Is there any way we can configure to use the bean definition from ConfigurationA class instead of ConfigurationB?
Why can't I use #Autowired in this case?
#SpringBootApplication
public class Application {
#Autowired
BookingService bookingService;
public static void main(String[] args) {
bookingService.book("Alice", "Bob", "Carol");
}
}
but can use #Bean
#SpringBootApplication
public class Application {
#Bean
BookingService bookingService() {
return new BookingService();
}
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(Application.class, args);
BookingService bookingService = ctx.getBean(BookingService.class);
bookingService.book("Alice", "Bob", "Carol");
}
}
Aren't the two ways to generate BookingService the same thing?
#Bean and #Autowired do two very different things. The other answers here explain in a little more detail, but at a simpler level:
#Bean tells Spring 'here is an instance of this class, please keep hold of it and give it back to me when I ask'.
#Autowired says 'please give me an instance of this class, for example, one that I created with an #Bean annotation earlier'.
Does that make sense? In your first example, you're asking Spring to give you an instance of BookingService, but you're never creating one, so Spring has nothing to give you. In your second example, you're creating a new instance of BookingService, telling Spring about it, and then, in the main() method, asking for it back.
If you wanted, you could remove the two additional lines from the second main() method, and combine your two examples as below:
#SpringBootApplication
public class Application {
#Autowired
BookingService bookingService;
#Bean
BookingService bookingService() {
return new BookingService();
}
public static void main(String[] args) {
bookingService.book("Alice", "Bob", "Carol");
}
}
In this case, the #Bean annotation gives Spring the BookingService, and the #Autowired makes use of it.
This would be a slightly pointless example, as you're using it all in the same class, but it becomes useful if you have the #Bean defined in one class, and the #Autowired in a different one.
#Bean
BookingService bookingService() {
return new BookingService();
}
Annotating #Bean only registers the service as a bean(kind of an Object) in the spring application context. In simple words, it is just registration and nothing else.
#Autowired
BookingService bookingService;
Annotating a variable with #Autowired injects a BookingService bean(i.e Object) from Spring Application Context.
(i.e) The registered object with #Bean annotation will be injected to the variable annotated with #Autowired.
Hope this clears your doubt!
great answer by #DaveyDaveDave
In the example instead of
#Bean
BookingService bookingService() {
return new BookingService();
}
You can use #Service annotation on BookingService class
Contrary to what the highest voted answer here claims, they are NOT two very different things. #Bean and #Autowired and interchangeable in most cases.
Suppose you have a #Bean method that returns an instance of a Car. You can literally get rid of that bean method and add #Component on the Car class and then autowire it.
And vice versa. Whatever class you have instantiated using #Autowired, you can instantiate it inside a class with #Configuration annotation using #Bean on the method.
Places where you will use #Bean instead of #Autowired
1>You do not have access to change the class to add #Component annotation, hence you cannot autowire it.
2>You want to customize the instantiation of the class.
For example if you are instantiating a Resilience4J Circuit breaker class, if you do it inside a method with #Bean, you have the option of setting all the config using code like this
#Bean
public CircuitBreaker fooCircuitBreaker() {
CircuitBreakerConfig.Builder builder = CircuitBreakerConfig.custom().
slidingWindowSize(xxx).
failureRateThreshold(xxx).
waitDurationInOpenState(xxx)).
ignoreException(e -> {
if (e instanceof HttpStatusCodeException) {
HttpStatusCodeException httpStatusCodeException = (HttpStatusCodeException) e;
if (httpStatusCodeException.getStatusCode().is4xxClientError()) {
return true;
}
}
return false;
});
circuitBreakerRegistry.addConfiguration(xxx, builder.build());
return circuitBreakerRegistry.circuitBreaker(xxx, xxx);
}
Here's good article about #Autowired annotation: http://www.baeldung.com/spring-autowire
The #Autowired annotation can instantiate your injectables by defining #ComponentScan("namespace.with.your.components.for.inject") on config class
#Configuration
#ComponentScan("com.baeldung.autowire.sample")
public class AppConfig {}
All components must be marked by #Component annotation. It replaces the #Bean annotation.
#Bean is just for the metadata definition to create the bean(equivalent to tag). #Autowired is to inject the dependancy into a bean(equivalent to ref XML tag/attribute).
From the Spring 5 docs
When #Bean methods are declared within classes that are not annotated
with #Configuration they are referred to as being processed in a
'lite' mode. Bean methods declared in a #Component or even in a plain
old class will be considered 'lite', with a different primary purpose
of the containing class and an #Bean method just being a sort of bonus
there. For example, service components may expose management views to
the container through an additional #Bean method on each applicable
component class. In such scenarios, #Bean methods are a simple
general-purpose factory method mechanism.
Unlike full #Configuration, lite #Bean methods cannot declare
inter-bean dependencies. Instead, they operate on their containing
component’s internal state and optionally on arguments that they may
declare. Such an #Bean method should therefore not invoke other #Bean
methods; each such method is literally just a factory method for a
particular bean reference, without any special runtime semantics. The
positive side-effect here is that no CGLIB subclassing has to be
applied at runtime, so there are no limitations in terms of class
design (i.e. the containing class may nevertheless be final etc).
The #Bean methods in a regular Spring component are processed
differently than their counterparts inside a Spring #Configuration
class. The difference is that #Component classes are not enhanced with
CGLIB to intercept the invocation of methods and fields. CGLIB
proxying is the means by which invoking methods or fields within #Bean
methods in #Configuration classes creates bean metadata references to
collaborating objects; such methods are not invoked with normal Java
semantics but rather go through the container in order to provide the
usual lifecycle management and proxying of Spring beans even when
referring to other beans via programmatic calls to #Bean methods. In
contrast, invoking a method or field in an #Bean method within a plain
#Component class has standard Java semantics, with no special CGLIB
processing or other constraints applying.
I would have expected that the following code throws an exception / bean1.bean2 to be null and that the init method would not be executed. However, the code below runs fine and prints:
Should never be invoked
Expected null but is ch.litebeans.Bean2#402bba4f
So for me it looks like lite beans behave the same as beans constructed from an #Configuration annotated class. Can someone point out in which scenario this is not the case?
.
package ch.litebeans;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(ApplicationConfig.class);
Bean1 bean1 = ctx.getBean(Bean1.class);
System.out.println("Expected null but is " + bean1.getBean2());
}
}
package ch.litebeans;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
#Configuration
#ComponentScan(basePackages = {"ch.litebeans"})
public class ApplicationConfig {}
package ch.litebeans;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
public class Factory1 {
#Bean
public Bean1 getBean1(Bean2 bean2){
return new Bean1(bean2);
}
}
package ch.litebeans;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
#Component
public class Factory2 {
#Bean(initMethod = "init")
public Bean2 getBean2(){
return new Bean2();
}
}
package ch.litebeans;
public class Bean1 {
private Bean2 bean2;
public Bean1(Bean2 bean2){
this.bean2 = bean2;
}
public Bean2 getBean2(){
return bean2;
}
}
package ch.litebeans;
public class Bean2 {
public void init(){
System.out.println("Should never be invoked");
}
}
EDIT:
Based on the explanation of Mike Hill I added an example demonstrating the difference:
public class BeanLiteRunner {
public static void main(String[] args) {
AnnotationConfigApplicationContext acac = new AnnotationConfigApplicationContext(MyComponent.class,
MyConfiguration.class);
MyComponent.MyComponentBean1 componentBean1 = acac.getBean(MyComponent.MyComponentBean1.class);
MyComponent.MyComponentBean1 componentBean2 = acac.getBean(MyComponent.MyComponentBean1.class);
MyConfiguration.MyConfigurationBean1 configurationBean1 = acac.getBean(MyConfiguration
.MyConfigurationBean1.class);
MyConfiguration.MyConfigurationBean1 configurationBean2 = acac.getBean(MyConfiguration
.MyConfigurationBean1.class);
}
}
#Component
public class MyComponent {
#Bean
public MyComponent.MyComponentBean1 getMyComponentBean1(){
return new MyComponent.MyComponentBean1(getMyComponentBean2());
}
#Bean
public MyComponent.MyComponentBean2 getMyComponentBean2(){
return new MyComponent.MyComponentBean2();
}
public static class MyComponentBean1{
public MyComponentBean1(MyComponent.MyComponentBean2 myComponentBean2){
}
}
public static class MyComponentBean2{
public MyComponentBean2(){
System.out.println("Creating MyComponentBean2");
}
}
}
#Configuration
public class MyConfiguration {
#Bean
public MyConfigurationBean1 getMyConfigurationBean1(){
return new MyConfigurationBean1(getMyConfigrationBean2());
}
#Bean
public MyConfigurationBean2 getMyConfigrationBean2(){
return new MyConfigurationBean2();
}
public static class MyConfigurationBean1{
public MyConfigurationBean1(MyConfigurationBean2 myConfigurationBean2){}
}
public static class MyConfigurationBean2{
public MyConfigurationBean2(){
System.out.println("Creating MyConfigrationBean2");
}
}
}
The output is as expected
> Creating MyComponentBean2
> Creating MyComponentBean2
> Creating MyConfigrationBean2
This is not a bug. Spring's lite bean definitions are automatically added to the context during the component scan. Bean definitions using a factory method (i.e., all #Bean-defined beans) will automatically attempt to autowire parameters using the current context. See ConstructorResolver#instantiateUsingFactoryMethod for more details.
The referenced documentation is perhaps not entirely clear. The primary differentiation between "lite" and "full" bean configurations is strictly the proxying that is done in "full" (#Configuration) mode. Take for example what would happen if we instead defined our beans in a #Configuration class:
#Configuration
public MyConfiguration {
#Bean
public Bean1 bean1() {
return new Bean1(bean2());
}
#Bean
public Bean2 bean2() {
return new Bean2();
}
}
The call to bean2() from within bean1() will actually reference the singleton bean2 instance from the context rather than directly calling the bean2() method as implemented. In fact, it doesn't matter how many bean2() method calls are made from within that configuration class -- the real bean2 method will only be executed one time.
"Lite"-mode does not proxy these methods, meaning that each bean2() method call will actually directly reference the method implementation and will not return the bean that is in the context. Rather, it will create a new separate instance that is not tracked by the context (as is the default Java behavior).
I wish to perform a couple of setup methods within my Spring Context.
I currently have the following code but it doesn't work as I am saying they are beans and have no return type.
#Configuration
#Component
public class MyServerContext {
...
// Works
#Bean
public UserData userData() {
UserData userData = new AWSUserDataFetcher(urlUtil()).fetchUserData();
return userData;
}
// Doesn't work
#Bean
public void setupKeyTrustStores() {
// Setup TrustStore & KeyStore
System.setProperty(SYS_TRUST_STORE, userData().get(TRUST_STORE_PATH));
System.setProperty(SYS_TRUST_STORE_PASSWORD, userData().get(TRUST_STORE_PASSWORD));
System.setProperty(SYS_KEY_STORE, userData().get(KEY_STORE_PATH));
System.setProperty(SYS_KEY_STORE_PASSWORD, userData().get(KEY_STORE_PASSWORD));
// Prevents handshake alert: unrecognized_name
System.setProperty(ENABLE_SNI_EXTENSION, "false");
}
...
}
How can I run this method automatically by the #Configuration context without the #Bean annotation?
You can use the #PostConstruct annotation instead of #Bean:
#Configuration
#Component
public class MyServerContext {
#Autowired
private UserData userData; // autowire the result of userData() bean method
#Bean
public UserData userData() {
UserData userData = new AWSUserDataFetcher(urlUtil()).fetchUserData();
return userData;
}
#PostConstruct
public void setupKeyTrustStores() {
// Setup TrustStore & KeyStore
System.setProperty(SYS_TRUST_STORE, userData.get(TRUST_STORE_PATH));
System.setProperty(SYS_TRUST_STORE_PASSWORD, userData.get(TRUST_STORE_PASSWORD));
System.setProperty(SYS_KEY_STORE, userData.get(KEY_STORE_PATH));
System.setProperty(SYS_KEY_STORE_PASSWORD, userData.get(KEY_STORE_PASSWORD));
// Prevents handshake alert: unrecognized_name
System.setProperty(ENABLE_SNI_EXTENSION, "false");
}
...
}
Use #PostConstruct instead of #bean
#PostConstruct
Due to the Weld Reference injection and initialization happens in this order;
First, the container calls the bean constructor (the default
constructor or the one annotated #Inject), to obtain an instance of
the bean.
Next, the container initializes the values of all injected fields of
the bean.
Next, the container calls all initializer methods of bean (the call
order is not portable, don’t rely on it).
Finally, the #PostConstruct method, if any, is called.
So, the purpose of using #PostConstruct is clear; it gives you a chance to initialize injected beans, resources etc.
public class Person {
// you may have injected beans, resources etc.
public Person() {
System.out.println("Constructor is called...");
}
#PostConstruct
public void init() {
System.out.println("#PostConstruct is called...");
} }
So, the output by injecting a Person bean will be;
Constructor is called...
#PostConstruct is called...
One important point about #PostConstruct is, it won't be invoked if you try to inject and initialize bean through producer methods. Because using a producer method means that you are programmatically creating, initializing, and injecting your bean with new keyword.
Resource Link:
CDI Dependency Injection #PostConstruct and #PreDestroy Example
Why use #PostConstruct?
I recently started working at a place that uses Java configuration for Spring as opposed to XML and so far I'm loving it.
My question is the following:
If we have a #Configuration annotated class A that imports another #Configuration annotated class B, what is the proper, type-safe way for a bean defined in A to depend on a bean defined in B.
Here's an example I saw in a blog (https://blog.codecentric.de/en/2012/07/spring-dependency-injection-styles-why-i-love-java-based-configuration/):
#Configuration
public class PartnerConfig {
#Bean
public PartnerService partnerService() {
return new PartnerServiceImpl();
}
}
#Configuration
#Import(PartnerConfig.class)
public class CashingConfig {
#Autowired
private PartnerConfig partnerConfig;
#Bean
public CashingService cashingService() {
return new CashingServiceImpl(partnerConfig.partnerService());
}
}
As a second part to my question, if I was to do the above, would Spring interpret as a bean dependency? That is, when I do
partnerConfig.partnerService()
in the example above, am I getting Spring to fetch me the partnerService bean, or am I just calling a regular java method and creating a new instance of the PartherService (which is NOT what I want, since the bean should be a singleton) ?
EDIT:
It has been suggested to use a #Qualifier. Would this work?
#Configuration
public class PartnerConfig {
#Bean
#MyCustomQualifier
public PartnerService partnerService() {
return new PartnerServiceImpl();
}
}
#Configuration
#Import(PartnerConfig.class)
public class CashingConfig {
#Bean
public CashingService cashingService(#MyCustomQualifier PartnerService partnerService) {
return new CashingServiceImpl(partnerService);
}
}
I recommend giving the docs a read: http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/annotation/Bean.html
Refer to the section:
#Bean Methods in #Configuration Classes
This sums it up very well.
Typically, #Bean methods are declared within #Configuration classes. In this case, bean methods may reference other #Bean methods in the same class by calling them directly. This ensures that references between beans are strongly typed and navigable.
Also take a look at: http://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/context/annotation/Configuration.html
Section:
Composing #Configuration classes
Just add the dependency as an argument to the #Bean annotated method and remove the autowiring of the configuration.
#Configuration
#Import(PartnerConfig.class)
public class CashingConfig {
#Bean
public CashingService cashingService(PartnerService partnerService) {
return new CashingServiceImpl(partnerService);
}
}
or simply autowire the PartnerService instead of the configuration.
#Configuration
#Import(PartnerConfig.class)
public class CashingConfig {
#Autowire
private PartnerService partnerService;
#Bean
public CashingService cashingService() {
return new CashingServiceImpl(partnerService);
}
}