Usage of #Bean annotation - java

Suppose I have the following Spring context configuration:
#Configuration
public class Configuration {
#Bean
public A a() {
return new A(b());
}
public B b() {
return new B();
}
}
Should one annotate b() with #Bean if the only place where B instance needed is within a() for A instance construction?

If B is a plan Java class (no Spring annotations) then no, You can use current configuration. As this is a private member of A class.
But if you have methods that need to be managed by spring (inside B class), like #PostConstruct or #PreDestroy, than you should make a Bean out of B class:
#Bean
public A a(B b) {
return new A(b);
}
#Bean
public B b() {
return new B();
}
Such cases are:
resource to be closed on shutdown/close
executors to be closed on shutdown
jdbc connections
etc

Related

Spring beans initialization through method

I have a little question about bean creation that bothers me a lot.
For example I have classes
public class A {
B b;
public A(B b) {
this.b = b;
}
}
public class B {}
And I want to make beans for them like this:
#Configuration
public class Config {
#Bean
public B beanB() {
return new B();
}
//version 1
#Bean
public A beanA() {
return new A(beanB())
}
//version 2
#Bean
public A beanA(B beanB) {
return new A(beanB)
}
}
So, my question is what is the right way to create bean A?
I think that the right one is version 2, because in the version 1 I think beanB can be invoked 2 times: on the creation of beanA and when spring will create it for it's context. But I can't find anything that will prove my opinion.
The "right" way is to do it the way the documentation, i.e. the javadoc of #Bean, shows it:
#Bean Methods in #Configuration Classes
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. Such so-called 'inter-bean references' are guaranteed to respect scoping and AOP semantics, just like getBean() lookups would. These are the semantics known from the original 'Spring JavaConfig' project which require CGLIB subclassing of each such configuration class at runtime. As a consequence, #Configuration classes and their factory methods must not be marked as final or private in this mode. For example:
#Configuration
public class AppConfig {
#Bean
public FooService fooService() {
return new FooService(fooRepository());
}
#Bean
public FooRepository fooRepository() {
return new JdbcFooRepository(dataSource());
}
// ...
}
That means version 1 in the question code.
Spring dynamically subclasses AppConfig, so only one instance is created no matter how many times the method is called, e.g. functionally something like this:
public class $dynamic$ extends AppConfig {
private FooRepository cachedFooRepository;
#Override
public FooRepository fooRepository() {
if (this.cachedFooRepository == null)
this.cachedFooRepository = super.fooRepository();
return cachedFooRepository;
}
}

Best practice to use #Configuration Bean in another #Configuration class

I have to work with existing library of my company which has bunch of #Bean packaged in #Configuration in Spring project but would be added as dependency for my project. The situation would be similar to
#Configuration
Class A{
#Bean
B b(){
return new B()
}
}
#Configuration
Class C{
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
Should I initialized A using new operator in C and call method b or should I #Autowire B in C directly.
There are multiple ways you can do this
By field Autowiring
#Configuration
Class C{
#Autowire
private B b;
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
By constructor Autowiring (Personally i prefer using constructor Autowiring which will be help during test cases)
#Configuration
Class C{
private B b;
#Autowire
public C(B b){
this.b=b;
}
#Bean
D d(){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
Or you can just add it as method arguments spring will resolve it
#Configuration
Class C{
#Bean
D d(B b){
D d = new D();
//TODO: How do I use instance of B here
d.someConfiguration(B b);
return d;
}
}
When you include the library sa a dependency, then when springboot initializes it scans the #Configuration files in those libraries as well. So the beans declared in those are already available in spring context.
So what you can do is just include it as a method parameter
#Configuration
Class C{
#Bean
D d(B b){
D d = new D();
d.someConfiguration(b);
return d;
}
}
As soon as spring see that you want a bean if type B it will search and give u an instance.
I would say its evil to use new in spring :)

Provide single #Bean that can be used to inject in multiple interfaces

Consider the following piece of code
public interface Iface1 { }
public interface Iface2 { }
public class A implements Iface1, Iface2 {
}
#Configuration
public class AutoConfig {
#Bean
Iface1 provideIface1Impl() {
return new A(); // instance no 1234
}
#Bean
#ConditionalOnBean(A.class)
#Autowired
Iface2 provideIface2Impl(A aImpl) {
return aImpl;
}
}
I would like the second #Bean method to be autowired with the instance from the first one (1234) and I'd like the second #Bean method to return the same instance, so that I can use the same instance for clients of Iface1 and Iface2.
Current problem is that spring doesn't run the second #Bean because there is no #Bean of type A.class - the created bean is considered as Iface1 even though it is of type A.
Just define bean A. When injecting IFace1 and Iface2 they will automatically resolve to A (if A is the only implementation of course).
#Bean
public A a() {
return new A();
}
I think you should try to define only one #Bean. It will create a singleton:
#Bean
public A a() {
return new A();
}
Then just use the name of this bean in #Qualifier annotation:
#Autowired
#Qualifier("a")
private Iface1 iface1;
#Autowired
#Qualifier("a")
private Iface2 iface2;
Additionally to what others have answered, I'd like to cover that part of the question that touches bean's dependencies.
To inject a dependency to a #Bean-annotated method, there are two ways:
Call another #Bean-method directly
Add parameter to the method
Examples of both:
#Configuration
public class AppConfig {
#Bean
public Foo foo() {
return new Foo();
}
#Bean
public Bar bar() {
return new Bar(foo());
}
#Bean
public Baz baz(Foo foo) {
return new Baz(foo);
}
}
So your provideIface2Impl could look like this:
#Bean
Iface2 provideIface2Impl(A aImpl) {
return aImpl;
}
// or...
#Bean
Iface2 provideIface2Impl() {
return (Iface2)provideIface1Impl();
}
But don't use it this way, it will lead to subtle bugs like double-proxying or "No unique bean of type" error, etc. Prefer what Gorazd suggested.

Why spring automatically #Autowitred fields in non-managed classes

As far as I know spring provides some ways to inject beans into non-managed classes.
It can be done explicitly with AutowireCapableBeanFactory. (How to inject dependencies into a self-instantiated object in Spring?)
But I've faced strange (IMHO) behavior, when spring performs such injection automatically.
Here is an example with spring batch,
Configuration:
#SpringBootConfiguration
public class ProcessorJobConfig {
//.....
#Bean(name = "pullRestTemplate")
public RestTemplate createPullRestTemplate() {
RestTemplate restTemplate = restTemplateBuilder.build();
return restTemplate;
}
#Bean(name = "step")
public Step step(#Autowired ItemReader<Measurement> itemReader,
#Autowired ItemProcessor<Measurement, Event> itemProcessor,
#Autowired ItemWriter<Event> itemWriter) {
return stepBuilderFactory.get("step")
.<Measurement, Event>chunk(Integer.MAX_VALUE)
.reader(itemReader)
.processor(itemProcessor)
.writer(itemWriter)
.build();
}
#Bean(name = "restProcessorJob")
public Job job(#Qualifier("step") Step step) throws Exception {
return jobBuilderFactory.get("restProcessorJob")
.start(step)
.build();
}
#Bean
public ItemReader<Measurement> itemReader() {
RestMeasureReader restMeasureReader = new RestMeasureReader(); // Use new() explicitly
return restMeasureReader;
}
//.....
}
Reader:
public class RestMeasureReader implements ItemReader<Measurement> {
private static final Logger LOGGER = LoggerFactory.getLogger(RestMeasureReader.class);
/**
* NOTE: This field will be injected automatically by spring, even we are using new() to create instance of this class.
*/
#Autowired
#Qualifier("pullRestTemplate")
private RestTemplate restTemplate;
#Override
public Measurement read() throws Exception, UnexpectedInputException, ParseException, NonTransientResourceException {
// do some stuff
}
}
And application itself
#EnableBatchProcessing
#EnableTask
#SpringBootApplication
public class TestAutowiredTaskApplication {
public static void main(String[] args) {
SpringApplication.run(TestAutowiredTaskApplication.class, args);
}
}
Even I use explicit new() to instantiate RestMeasureReader, its RestTemplate field will be injected afterwards.
Is it normal behavior? I do not expect spring to automatically inject fields when creating object with new().
If you are talking about using new inside of your #Configuration class, then yes it is normal behavior. This is you Spring java configs. So it's is Spring managed context. You are not going to call itemReader() in your code explicitly.
So, when you are going to do this:
#Autowired
private ItemReader<Measurement> iterReader;
you will get instance of your RestMeasureReader from Spring's IoC.
But if you will try to do explicitly call new RestMesureReader() inside of your code, you will get a new instance of RestMesureReader not a Spring Proxy with injected #Autowired fields.
Try to remove #Bean from your itemReader() method declaration and won't event be able to autowire RestMesureReader.
So basically #Configuration classes are just a Spring configuration, not a real java code. Even though you call new Spring will still return you a proxy class.
For more information check this guide.
Spring processes beans returned by methods that are annotated with #Bean
This allows you to use autowiring or livecycle callbacks when using Java configuration.
A more minimalistic example:
#Configuration
public class MyConfiguration {
#Bean
public A a() {
return new A();
}
static class A {
#Autowired
private B b;
#PostConstruct
public void onPostConstruct() {
System.out.println("postConstruct: " + b);
}
}
#Component
static class B {
}
}
Here, even if the bean named a is created manually, Spring will inject dependencies (b) and call #PostConstruct callbacks.

How to AutoWire an object without Spring XML context file?

I have an Interface with Component annotation and some classes that implemented it as follows:
#Component
public interface A {
}
public class B implements A {
}
public class C implements A {
}
Also, I have a class with an Autowired variable like this:
public class Collector {
#Autowired
private Collection<A> objects;
public Collection<A> getObjects() {
return objects;
}
}
My context file consists of these definitions:
<context:component-scan base-package="org.iust.ce.me"></context:component-scan>
<bean id="objectCollector" class="org.iust.ce.me.Collector" autowire="byType"/>
<bean id="b" class="org.iust.ce.me.B"></bean>
<bean id="c" class="org.iust.ce.me.C"></bean>
And in the main class, I have some codes as follows:
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
B b = (B) context.getBean("b");
C c = (C) context.getBean("c");
Collector objectCollector = (Collector) context.getBean("objectCollector");
for (A object : objectCollector.getObjects()) {
System.out.println(object);
}
Output:
org.iust.ce.me.B#1142196
org.iust.ce.me.C#a9255c
These codes work well, but for some reasons I’m not willing to use xml context file. Besides it, I prefer to create the objects with the new operator rather than using the getBean() method. Nevertheless, since the AutoWiring is really good idea in programming, I don’t want to lose it.
Now I have two questions!!
how can I AutoWire classes that implements the A Interface without using the xml context file?
Is it possible at all?
when I change the scope of a bean from singlton to
prototype as follows:
<bean id="b" class="org.iust.ce.me.B" scope="prototype"></bean>
and instantiate several beans of it, only the bean which was instantiated during creating context, is injected into AutoWired variable. Why?
Any help will be appreciated.
Not sure the version of Spring you are using. But currently you can use #Configuration to replace .xml. Take a look at #Configuration
Below is the code in documentation
#Configuration
public class ServiceConfig {
private #Autowired RepositoryConfig repositoryConfig;
public #Bean TransferService transferService() {
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
#Configuration
public interface RepositoryConfig {
#Bean AccountRepository accountRepository();
}
#Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
public #Bean AccountRepository accountRepository() {
return new JdbcAccountRepository(...);
}
}
#Configuration
#Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
public #Bean DataSource dataSource() { /* return DataSource */ }
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
Provided the classes to be managed have been correctly annotated, Spring can scan the application's files to get the information it needs without any xml or java configuration files at all.
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.scan("com.something.something.etc");
context.refresh();
...context.getBean("name_of_bean");
Note AnnotationConfigApplicationContext is instantiated without any arguments. context.scan("..."); takes a string that tells Spring where to look. i.e. packagescom.something.something.etc.one
com.comething.something.etc.twowill be scanned, and classes within those packages annotated with #Component, #Autowired, etc. will be instatiated and injected where needed.
This approach doesn't seem to be as well documented.
1- You need to write another class that will do the operation. write #Component to B and C class.
public static void main(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
InitClass initClass = (InitClass) context.getBean("initClass");
}
public class InitClass{
#Autowired
public B b;
#Autowired
public C c;
}
with this you will get B and C without using xml.
2- http://static.springsource.org/spring/docs/3.0.0.M3/reference/html/ch04s04.html Bean scopes are detailed mentioned here. If you want always a new object you should use prototype but creating a new one will be done in different classes. In the same class you should add a new reference.
like
public class InitClass{
#Autowired
public A a1;
#Autowired
public A a2;
}

Categories