I'm learning about dependency injection in Spring and I have this code:
#Autowired
private CamelContext context;
#Autowired
private Environment environment;
#Autowired
protected CamelContext createCamelContext(){
return context;
}
...
}
I understand that context and environment bean is injected in this class, but what I don't understand is what exactly is injected with this code:
#Autowired
protected CamelContext createCamelContext(){
return context;
}
I don't understand this kind of injection. What exactly is happen here? What is the difference between this method injection and this simple method without injection:
protected CamelContext createCamelContext(){
return context;
}
Any feedback will be apreciated! Thank you!
Methods annotaded with #Autowired are either setters or config methods. They are called after bean creation and can be used for initialization. All the arguments of these methods will be automatically injected by Spring. From Spring javadoc:
Autowired Methods
Config methods may have an arbitrary name and any
number of arguments; each of those arguments will be autowired with a
matching bean in the Spring container. Bean property setter methods
are effectively just a special case of such a general config method.
Such config methods do not have to be public.
But in your case createCamelContext() has no arguments and does no initialization either. So I don't see any reason to declare this method.
In this scenario, #Autowired is pretty much equivalent to #Bean on createCamelContext and #Inject on context. Autowiring beans occurs by type if you don't give a #Qualifier, so your code will basically take your #Autowired/#Inject CamelContext context and go looking for a CamelContext to fill in the missing value, which it will find as provided by #Autowired/#Bean createCamelContext.
The difference between an annotated createCamelContext and an un-annotated one is that Spring will not have that method in its Beans, and so it won't find the method when looking for a #Bean to #Inject.
In your specific case, the value context goes looking for a CamelContext, and finds one in the form of createCamelContext. At this point, createCamelContext looks up the value of context, which is null. It returns this value, which is injected into context. Therefore, at any point in time, referring to context or createCamelContext should always yield null.
Related
what is the main difference between injecting objects with #Autowired and injecting without it ?
I know that spring will initialize the bean , but what it is really offering ?
There are several ways to configure Spring beans and inject dependencies using Spring. One way is by using constructor injection, where the constructor of your Spring bean has arguments which are the dependencies that should be injected:
#Component
public class MyBean {
private final SomeDependency something;
#Autowired
public MyBean(SomeDependency something) {
this.something = something;
}
}
However, since Spring 4.3, it is not necessary anymore to use #Autowired on such a constructor (click link for Spring documentation). So you can write it without the #Autowired:
#Component
public class MyBean {
private final SomeDependency something;
public MyBean(SomeDependency something) {
this.something = something;
}
}
This will work exactly the same as the code above - Spring will automatically understand that you want the dependency to be injected via the constructor. The fact that you can leave out #Autowired is just for convenience.
So, to answer your question: there is no difference.
#Autowired (so the injection) in some situation cannot be used, an example is if your autowired bean not ready because of some async stuff but in the target bean you want to use that.
So in this situation do not use inject (#Autowired) it is better to inject the ApplicationContext and in the exact moment get your bean from there by name or by class (there is a lot off possibilities there).
You can consider the #Autowired with the #Lazy annotation too.
This question already has answers here:
Difference between #Bean and #Autowired
(6 answers)
Closed 4 years ago.
What is the difference between #Bean and #Autowired in Spring?
As far as I understood we can use both to inject dependencies, #Autowired when the interface was implemented just in one class, and #Bean, when the interface was implemented in more than one class, in the last case #configuration, is required.
thanks in advance
In short #Bean is producer and #Autowired is consumer, #Bean annotation let spring know instance of this class and it hold for it and #Autowired annotation ask for please give me instance of class which we created with #Bean annotation.
more detailed answer find here
When you use #Bean you are telling to Spring that:
this is the object that I want you to put within your stack and later I will ask
about it from you
And When you use #Autowired you are telling to Spring that:
Now please give me the object that I already told you to keep it in your stack (means the #Bean object)
When you use #Bean you are responsible for providing an Id and calling that Id when you wish to use that particular object using getBean() method.
Autowired helps avoid the calling part and returns an object everytime it is needed. Spring handles the job of returning the appropriate object and helps reduce additional syntax for referring to a particular bean.
Spring provides a very nice documentation about Autowired and Bean API
#BEAN
#Target(value={METHOD,ANNOTATION_TYPE})
#Retention(value=RUNTIME)
#Documented
public #interface Bean
Indicates that a method produces a bean to be managed by the Spring
container.
On Bean #Target annotation confirms that it can be applied over a METHOD.
#AUTOWIRED
#Target(value={CONSTRUCTOR,METHOD,PARAMETER,FIELD,ANNOTATION_TYPE})
#Retention(value=RUNTIME)
#Documented
public #interface Autowired
Marks a constructor, field, setter method or config method as to be autowired by Spring's dependency injection facilities. This is an alternative to the JSR-330 Inject annotation.
On Autowired #Target confirms that it can be applied over a CONSTRUCTOR,METHOD,PARAMETER,FIELD.
IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies, that is, the other objects they work with, only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean.
I'm new to Spring, I would like to know:
I have a java class annotated with #Component (spring) and inside I have a method annotated with #PostConstruct. The class is then referenced by #Autowired annotated field in another class. Can I assume that the class is only injected after #PostConstruct is called?
#Component
class AuthenticationMetrics {
private static final MetricRegistry metrics = new MetricRegistry();
final Counter requestsTotal;
final Meter guestLogins;
final Meter kfUserLogins;
final Timer guestLoginResponseTime;
final Timer kfLoginResponseTime;
#PostConstruct
public void populateMetricsRegistry() {
metrics.counter("authentication.requests.totals");
}
}
If you are asking is injection of given class happening after #PostConstruct in that bean is called, then the answer is yes - #PostConstruct is executed before bean is considered as "injectable"
If you are asking if #PostConstruct on given bean is executed after all injections has been done (on the same bean) - then yes - #PostConstruct is executed after injections are commited to given bean. This is the reason it exists. Normally you could put #PostConstruct actions into the constructor. However, when new object is created (constructor is called) injections are not performed yet - so any initialization that depends on injected objects would fail due to NPE. That is why you need #PostConstruct
The handling of annotations such as #PostConstruct, #Resource, #PreDestroy is done via a BeanPostProcessor, in this case the CommonAnnotationBeanPostProcessor. You can see in the following diagram from Spring that these BPP's are handled after Dependency Injection but before Bean Ready For Use (Which means as much as injectable).
Yes. Bean creation workflow is:
constructior call
#Autowired fields
#Autowired setters
BeanPostProcessor's postProcessBeforeInitialization(), i.e. #PostConstruct called by CommonAnnotationBeanPostProcessor
InitializingBean.afterPropertiesSet()
BeanPostProcessor's postProcessAfterInitialization()
Bean is ready and can be injected to other bean
This is an example from the Spring documentation, section 6.12.5:
#Configuration
public class ServiceConfig {
#Autowired
private AccountRepository accountRepository;
#Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
My question is: why must it happen that accountRepository is created before it's used by new TransferServiceImpl()? Offhand, I don't see how Spring could know that the second one depends on the first one being set up (unless it goes through the transferService() bytecode). Is it because something about the order in which Spring does things guarantees that the #Autowired variable is processed before the #Bean method could possibly be called? What is the processing order? What kinds of circumstances could cause Spring to process these out of order?
The reason I'm asking is that I have a case where something like this isn't working, i.e. the new is being executed with a null argument. Either the #Autowired variable is being set up too late, or it isn't set up at all (my guess is the latter, based on some log4j.logger.org.springframework.beans debugging output, but I'm not sure). The situation is of course much more complex--it's a largish application, and there are a few more #Autowired and #Bean definitions in the configuration class. Using #DependsOn hasn't helped. It will take a lot of time to narrow down the problem by deleting code until I can get a minimal example, but I wanted to see if I could get some insight into the problem by learning more details about how Spring processes things, before starting down the difficult code reduction path.
why must it happen that accountRepository is created before it's used
by new TransferServiceImpl()?
It doesn't. accountRepository may be seen to be null.
From the note in the documentation you linked (its more current version)
Make sure that the dependencies you inject that way are of the
simplest kind only. #Configuration classes are processed quite early
during the initialization of the context and forcing a dependency to
be injected this way may lead to unexpected early initialization.
Whenever possible, resort to parameter-based injection as in the
example above.
Also, be particularly careful with BeanPostProcessor and
BeanFactoryPostProcessor definitions via #Bean. Those should usually
be declared as static #Bean methods, not triggering the instantiation
of their containing configuration class. Otherwise, #Autowired and
#Value won’t work on the configuration class itself since it is being
created as a bean instance too early.
In summary, a Configuration class will end up being just another bean in the application context. As such, it will be processed by all registered BeanPostProcessor beans.
#Autowired is processed by AutowiredAnnotationBeanPostProcessor. Presumably, you're using AnnotationConfigApplicationContext which registers one automatically.
In your example, which is incomplete since
...but determining exactly where the autowired bean definitions are
declared is still somewhat ambiguous
However, we can assume some other configuration provided a bean definition for a AccountRepository bean. Once the application context instantiates the ServiceConfig bean, it can then post process it and inject #Autowired targets.
The only reason an #Autowired target could be null in a #Configuration bean instance is that you tried to read it before an AutowiredAnnotationBeanPostProcessor could process/inject it.
Consider a circular dependency. Take the #Configuration class in your snippet with an additional #ComponentScan of the following classes
#Component
class AccountRepository {
public AccountRepository(Foo foo) {}
}
#Component
class Foo {
public Foo(TransferService ts) {}
}
The #Configuration bean get initialized. AutowiredAnnotationBeanPostProcessor kicks off to process the accountRepository field. It looks for an AccountRepository bean and tries to initialize it. It needs a Foo bean to instantiate it (for constructor injection). It looks for a Foo bean and tries to initialize it. It needs a TransferService bean to instantiate it (for constructor injection). It looks for a TransferService bean and finds the #Bean factory method. It invokes it. The accountRepository hasn't been initialized yet, so remains null. You can verify this by putting a breakpoint in the #Bean method and browsing the stack trace.
Had you used a parameter injection as suggested in the quote above
Whenever possible, resort to parameter-based injection as in the example above.
Spring would've crashed and warned you
Caused by:
org.springframework.beans.factory.BeanCurrentlyInCreationException:
Error creating bean with name 'accountRepository': Requested bean is
currently in creation: Is there an unresolvable circular reference?
That's the workaround I ended up doing
I can't currently explain this.
I just move accountRepository to the method's param and annotated with #Autowired to solve this problem. But I don't know why. I think the reason is about Spring's init order.
#Configuration
public class ServiceConfig {
#Bean
public TransferService transferService(#Autowired AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
I've moved my code from Spring's XML configuration to Java Configuration. I have everything working, but I have a question about how I implemented prototype beans - mainly, while what I'm doing works, is it the best way to do this? Somehow it just feels off!
I wrote the bean class this way:
#Component
#Scope("prototype")
public class ProtoBean {
...
}
Then to use the bean - this is the part that I'm just not sure about, although it does work:
#Component
public class BeanUser implements ApplicationContextAware {
ApplicationContext context;
#Override
public void setApplicationContext(ApplicationContext context)throws BeansException
{
this.context = context;
}
public void getProtoBean() {
ProtoBean protoBean = context.getBean(ProtoBean.class);
}
}
This gets me a prototyped bean, and in unit tests I just mocked the context, called setApplicationContext with the mock, and had the getBean call of the mock return a mock ProtoBean. So all is well.
I did this in the XML by using a factory, but that didn't seem to work too well, so this is where I ended up. But is there a way to do this without the context? Or just a better way?
Thanks!
I don't think is so much an issue of Spring XML vs Java-base configuration, but one of matching dependency scopes. Since Spring can only do dependency injection on the singleton-scoped bean at creation time, you have to lookup the prototype-scoped bean on demand. Of course the current bean-lookup approach works, but creates a dependency on the ApplicationContext. I can suggest a few other possibilities but the root of the issue is really what is involved in producing a ProtoBean, and what trade-offs should you accept.
You could make BeanUser itself prototype-scoped, which would allow you to wire in the ProtoBean as a member. Of course the trade-off is you now have the same problem on the clients of BeanUser, but sometimes that would not be a problem.
Another path could be using something like a singleton-scoped ProtoBeanFactory to provide ProtoBean instances, and hiding dependency lookups within the ProtoBeanFactory.
Finally, you could use a scoped-proxy bean to effectively hide the factory. It uses AOP to do this, and isn't always clear to others what sort of voodoo you have going. With XML you'd use <aop:scoped-proxy/> on the bean declaration. For annotations you'd use:
#Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")