ProxyBeanMethods in Spring - java

Can someone give a real case example of how using boolean element proxyBeanMethods is going to change how the application's bean interact with one another ? From my understand setting proxyBeanMethods to false is similiar to using #Lazy annotation on the dependencies of a bean in which those dependencies will only be created once the methods that return them are called therefore improve the startup speed. Is there anything I'm missing ?

It isn't the same as #Lazy and this is also explained in the javadoc of the property.
The default is true meaning each #Bean method will get proxied through CgLib. Each call to the method will pass through the proxy and assuming singleton scoped beans, it will return the same instance each time the method is called.
When setting it to false no such proxy method will be created and each call to the method will create a new instance of the bean. It will act just as a factory method. This is basically the same as the so called Bean Lite Mode, or #Bean methods on non-#Configuration annotated classes.
Now the latter isn't the same as #Lazy which will only defer the construction to the moment it is needed.

Related

Spring caches the object returned from a bean method

Let's say I have a following bean method:
#Bean
public Queue invoiceRegenerationQueue() {
return new Queue(configurationManager.getQueue().getInvoiceRegenerationQueueName(), true);
}
and call this method somewhere in my code:
var binding = BindingBuilder
.bind(invoiceRegenerationQueue())
I have only just discovered that when I call this method I will always get the same object instead of different objects as I expected. I expected that Spring will only inject object from the context when I use #Autowired annotation, but it seems it also cached the object which is returned from the bean method. I mean I debugged that and every call to that method returns the same object like as if spring intercepts calls to that method and returns an object from cache.
I tried to google but haven't been able yet to find any references to that in documentation. Why does it work so? Does anyone know where I can read about such behaviour in docs?
I have only just discovered that when I call this method I will always get the same object instead of different objects as I expected.
That's correct. Spring modifies #Bean methods in #Configuration classes using bytecode manipulation techniques so that multiple calls to such a method will return the same instance - which looks strange if you look at the source code itself.
The reason is that most Spring beans are singletons, and you would not want multiple instances of those beans being created when the corresponding #Bean method is called multiple times.
This is explained in the following section in the Spring reference documentation: Further Information About How Java-based Configuration Works Internally

How to inject fields in bean-methods?

Sonar-linter think that right way to inject is:
#Bean
public Example example(DataSource datasource) {
return new Example(datasource)
}
but if only one method's using this field. I'm curious, why exactly one method? And maybe better do #Autowired?
Quote from Sonar's rule:
When #Autowired is used, dependencies need to be resolved when the class is instantiated, which may cause early initialization of beans or lead the context to look in places it shouldn't to find the bean. To avoid this tricky issue and optimize the way the context loads, dependencies should be requested as late as possible. That means using parameter injection instead of field injection for dependencies that are only used in a single #Bean method
As your Quote says, #Autowired needs the dependency to be resolved when the class is Initialzed. Parameter Injection instantiates the bean only when it‘s needed. This increases the effectivity of your Code.
The reason for the Single Method is caused by lifecycle of a Bean. By default Beans are singletons which means they are Shared like static Objects. So if multiple Objects will use the bean it is more effective to inject them with autowired because the possibility That it will be used is much higher and so you provide the Shared instance at Startup

Are beans fully initialized in constructor when using constructor injection with Spring?

When using constructor injection with Spring, is it safe to assume that all passed beans are fully initialized?
In other words, is it possible to do the same things in the constructor as in a method annotated with #PostConstruct when using the "classic" #Autowired mechanism? Or is it possible that some post-processing is executed on the passed beans after the constructor is called?
The whole point of using #PostConstruct is that , when you are using setter dependency injection , the constructor cannot be used to fully initialize the object and some initialization needs to be performed after all the setter methods have been called (since dependency needs to be injected).Please note that the annotation #PostConstruct is completely removed in java 11 and needs the addition of dependency javax.annotation-api for it to work.Also #PostConstruct can be annotated to only one method in a class and it will be executed only once in the bean lifecycle.
But by using constructor injection, we are essentially solving the problem of all the dependencies not yet injected when the constructor is invoked.So if you are using constructor injection you can probably not use #PostContruct.
Reference : https://docs.oracle.com/javaee/7/api/javax/annotation/PostConstruct.html
it is safe to assume that all dependencies specified as constructor parameters are initalised. other dependencies are not.

When is injected bean actually initialized?

I have the following scenario in my code base:
//this bean, which will be injected,
//is not annotated
public class HelperUtil {
//only default constructor with no args
public void doThis(String _in) {
//...
}
public void doThat() {
//...
}
}
In the below class we do the injection:
#Named
#Stateless
public class BusinessManager {
#PersistenceContext(unitName = "default")
private EntityManager em;
#Inject
private HelperUtil helperUtil ;
//...
}
Q1: When is the instance of HelperUtil which will be injected actually initialized by calling the default constructor? Is it done when the first client into which it is injected (like BusinessManager) is instantiated when the app server (in my case JBoss) starts (and that one will be initialized by the container because it is annotated as #Stateless)?
Q2: In the above exhibit, will HelperUtil remain a singleton as long as no client other than the container asks for an instance by calling the constructor directly and not obtaining an instance via DI?
Q3: What is the advantage of using DI and #Inject in this case vs. simply calling the constructor directly (HelperUtil helper = new HelperUtil();)?
It depends, but you can control these event to execute some code, for example:
If you need that your bean is executed when the app start you need to add #Startup annotation to your bean.
If you need to initialize your bean without access to other injected resources you can use the normal constructor.
If you need some method to be executed when the bean is initialized then use the #PostConstruct annotation in the method.
You need to remember that the creation depends on the scope of the bean, in you case, which is a stateless bean, the bean will be created if some client injects it and there are no other instance available, if is singleton then will bean created just once, in general the bean will be created when they are needed (a singleton bean initialize until the first client uses it, or at startup with the annotation)
EDIT:
For the third question, the advantage is that if you use a resource, or other bean inside your HelperUtil, they will be initialized with the proper values, for example, if you use an entity manager, or other beans inside your helper. If your helper will handle just things like static methods or other simple utilities then you are right, the advantage is none and you could simply manage like an static helper class, but if you need EE resources the you need the bean to be managed in order to get all injections and resources loaded
EDIT 2:
After some more years programming and using dependency injection in Java and C# Core, I can add: The question 3 is very open, using DI will allow your code to:
be less coupled, if you change your constructor, you then would have to go searching all the new ObjectModified(oldParams) to add the new parameters
more easy to test, because you can inject "fake objects" as dependencies, avoiding the need to load all the system and prepare the state for the test, for example, if you want to check some code that depends on the current hour, you could connect a fake provider in test mode to give always the same hour, or some sequence
Avoid cyclical dependency, where class A depends on B and B depends on A, normally this is more complex, like
ClasssA -> ClasssB -> ClasssC -> ClasssA
When this dependencies are present, you can start a modification, then modify the class that uses it, and so on... until somehow you find yourself modifying the same class as before!, so you start in a cycle because the communication path between your objects are complex.
When you use DI, this cycles can be detected early on, so you can rethink your architecture to avoid this productivity blackholes
DI is a very powerful tool to keep big projects maintainable, is now present in a lot of environments and frameworks because is very useful, if this still does not convince you, you can try start a project in Spring boot, PlayFramework, Net Core, Java EE, Ruby on Rails.... and many others that have include this as the normal flow and build a medium size app, then try without DI
Background: Everything within CDI operates within a Context. That being said
A managed bean's fields are instantiated, on request. From the spec:
When the container creates a new instance of a managed bean, session bean, or of any other Java EE component class supporting injection, the container must:
Initialize the values of all injected fields. The container sets the value of each injected field to an injectable reference.
What this means is that the first initialization of a dependent bean is when it's first called for, which is when the parent bean is initialized. Now, the JSF #ApplicationScoped has the eager="true" attribute, which allows beans of that scope to be initialized before they're needed by any other part of the application, on startup, EJB #Startup for the same effect on EJBs. CDI beans however, don't have that capability out of the box.
The default scope of CDI beans is #Dependent. What this means is that an injected bean inherits the scope of the injection target (except when the bean has its own scope; in that case, its own scope applies). In your case, HelperUtil is not going to live beyond the lifetime of that EJB, sorta like #RequestScoped
Related
how is the #RequestScoped bean instance provided to #SessionScoped bean in runtime here?
Non-lazy instantiation of CDI SessionScoped beans
JSF Named Bean, Eager application scoped (aka #ManagedBean(eager=true) )
I think its constructor is not called until the method is called like helperUtil.dothat(), its not when its containing bean is instantiated.
About all of the injected fields must be initialized by the container when the managed beans are instantiated like the other answer, its true, but all of the injected fields are injected with proxies so they are not the real objects so the real constructors aren't called.
If its constructor is called when its containing bean is instantiated then how about a #RequestScoped bean inside a servlet for example. The servlet is only instantiated one time but the injected #RequestScoped bean must be instantiated multiple times. If its true then surely the #RequestScoped annotation wouldn't work.
So by simply looking at those CDI annotations intention and name like "request" or "session", we know that the real CDI managed bean objects are made/ instantiated independent of the containing user bean instantiation.

Is there a way to get all beans with scope prototype that are injected via #Autowired?

Injecting bean with scope prototype with #Autowired usually doesn't work as expected. But when writing code, it's easy to accidentally inject a prototype.
Is there a way to get a list of all #Autowired fields and methods and to match that with a Spring AppContext to check for this?
One approach could be to override org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor(which is responsible for processing #Autowired, #Inject, #Resource etc) and perform the checks that you have mentioned in this overridden bean post processor. However, AutowiredAnnotationBeanPostProcessor gets registered with quite a few of the common custom namespaces (context:component-scan, context:annotation-config etc), so these custom annotations will have to be replaced with the corresponding bean variation and the overridden post processor also registered as a bean.

Categories