Spring Beans Configurations - spring

if we have
1- a case scenario where we have class A configured as singleton and a child class B as a member within Class A configured as prototype.
2- Another case scenario, which is the opposite to the first one, where we have Class A defined as prototype and Class B defined as singleton.
How Spring container is gonna initialize and deal with these two situations when request is made to these classes A and B?

Please take a look at this answer - Spring session-scoped beans as dependencies in prototype beans?
You can always inject a bean of wider scope (e.g. a singleton) into a
bean of narrower scope (e.g. a session-scoped bean), but to it the
other way around, you need a scoped-proxy.
This applies to your questions.
You are injecting narrower scope bean in wider scoped bean. (Prototype is narrower than singleton). It should work for you.
You are trying to inject wider scope bean into narrower scoped bean. You need to use a scoped-proxy.

Related

Inconvenient of #Value Annotation in Spring 3.0

I'm wondering if I add a #Value annotation on a property, the class who contains this property cannot be used by another one with a different value, Example :
MyClassUtil.java had
#Value("${some.value}")
private int _myProperty;
And of course there is one module.properties who contain :
some.value=10
Another class ClassA.java wants to use this class with value 10. Ok, no problem.
But another class ClassB.java wants to use this class but with another value : 20. I cannot do this if I'm not mistaken.
Because before #Value era, I could declare two beans in the moduleContext.xml without any problem.
So, is #Value pushes you to do some strong coupling ?
You are right that the annotation configuration can not be instance specific. It is important to understand the concept of bean definitions in bean factory.
Manual bean definition:
Single <bean> element in your XML config leads to a single bean definition. Multiple <bean> mean multiple definitions (regardless of a bean type).
Single #Bean method within #Configuration class leads to a single bean definition. Multiple #Bean methods mean multiple definitions (regardless of a bean type).
However when using component scan, classes annotated with #Component-like annotations are auto-registered as a single bean definition. There is no way you can register bean multiple times via component scan.
Similarly, annotation configurations (#Value, #Autowired, etc.) are type-wide. Your bean instances are always augmented and processed with the same effect (e.g. injecting the same value). There is no way you can alter annotation processing behaviour from instance to instance.
Is this tight coupling? It is not in its general understanding - bean factory (Spring) is still free to inject whatever it thinks is suitable. However it is more of a service lookup pattern. This simplifies your life when working with domain specific singletons. And most beans in an application context tend to be singletons, many of them domain specific (controllers, services, DAOs). Framework singletons (non-project specific reusable classes) should never use annotation based configuration - in this scope, it is an unwanted tight coupling.
If you need different bean instances, you should not use annotation configuration and define your beans manually.

inject beans into an abstract class with spring and java ee 5

I am injecting a spring-managed bean into an abstract class and it seems that it doesn't work. Here is an explanation of what I do, if it is not enough, I can edit the post and add some code:
implement the java code - 1 abstract class, 2 classes that inherit from it and the bean to be injected and used in the abstract class and thus by the subclasses.
define the bean in the spring config.
define the abstract class and 2 subclasses in the spring config.
define the first bean as a property of the abstract class bean.
result - it's not working.
Then I tried to move the injected bean from the abstract class into the two subclasses. Now it works.
So, did I do something wrong, or is it theoretically impossible to inject a bean into an abstract class with spring 3 and Java EE 5?
Is it theoretically impossible to inject a bean into an abstract class with spring 3 and Java EE 5?
Dependency Injection happens on an Object not its Class. Spring injects dependencies into managed beans which are Objects already instantiated by Spring. Since, an Abstract Class cannot be instantiated it would be conceptually wrong to think about DI here.
On a somewhat related note, you can also define a non-abstract Class as an abstract Spring bean by adding the attribute abstract=true to the <bean> tag. This indicates that the bean would not be instantiated and would serve as a mere template of properties that other beans can use through bean inheritance (which isn't related to Java inheritance at all).
In this context as well, (if you've configured it) the Dependency Injection would only happen for the child beans and not their parent bean since it has been defined as abstract. (Note: It's not mandatory for the parent bean to be abstract but it makes sense to do so when all it does is to act as a set of common bean properties.)

In spring batch framework, what is the difference between 'lazy-init=true' and 'scope=step'?

When I defined a 'MethodInvokingFactory' bean with 'scope=step', I got an error that the type of the bean can't be determined. It worked fine when I replaced 'scope=step' with 'lazy-init=true'. As per my knowledge, both are used for the late binding of the beans, except for that one difference. Are there any other differences between these two ways? Also, is my usage correct?
Please let me know your thoughts about this.
To answer to your question from low-level perspective:
lazy-init="true" means that bean will not be instantiated when the context is created, but will be created when it is referred e.g. by another bean. I think this is clear, also from #AravindA comment.
Scoped bean works in different manner. When context is created this bean is wrapped into additional proxy object (by default created by CGLIB), which is passed to the bean that refers it (this proxy is by default singleton, e.g. shared). So each time the method is invoked on the proxy in runtime Spring intersects the call, requests the factory to return the instance of the bean and invokes the method on that bean. The factory in its turn may lookup for "real" bean instance e.g. in HTTP request ("request" scope) or HTTP session ("session" scope) and/or create new instance if necessary. Late instantiation allows to initialize the scoped bean with "runtime" (scope) values, e.g. values from HTTP request/session which are obviously undefined when context was created. In particular "step"-scoped beans are bound to thread local (remember that steps are run in parallel for partitioning). So, scoped beans are dereferred when you call a method on them. Finally one can easily break this elegant Spring "ideology" by calling any method on scoped bean just after it is set to another bean (e.g. in the setter) :)
One thing to understand about lazy-initialization is that even though a bean
definition may be marked up as being lazy-initialized, if the lazy-initialized
bean is the dependency of a singleton bean that is not lazy-initialized, when the
ApplicationContext is eagerly pre-instantiating the singleton, it will have to
satisfy all of the singletons dependencies, one of which will be the
lazy-initialized bean!
Using a scope of Step is required in order to use late binding since the bean
cannot actually be instantiated until the Step starts, which allows the
attributes to be found. Because it is not part of the Spring container by
default, the scope must be added explicitly, either by using the batch namespace
or by including a bean definition explicitly for the StepScope (but not both):
<bean class="org.springframework.batch.core.scope.StepScope" />
Read here and here for more info
The scope="step" has nothing to do with Lazy initialization . It is use for late binding of parameters inside a "Step" .
the step scope is specifically for latebinding of job/step attributes and not really for late-binding of beans, meaning the spring bean context/factory will enhance stepscoped beans and look for attributes to set, e.g.
value="#{jobParameters[input.file.name]}

How to enforce restrictions on #Autowired

We use Spring in a project and #Autowired for automatically injecting dependencies. I would like to prohibit autowiring of certain beans from specific modules, so for example, it would be possible to autowire beans from module A in module B, but not in module C. Is it possible with Spring?
Unfortunately beans in single application context are flat i.e. they are all equivalent. However if you define two application contexts, parent and child, then beans from child have access to beans from parent but not the other way around. Beans defined in child context are simply invisible to parent.
In your case you place module A and B in parent context and C in child context.
The best way to approach the problem is through javax.inject qualifiers. Annotate your beans with the appropriate qualifier and then use it at the injection point:
#Autowired
#FooQualifier
private YourService service;
Otherwise it will soon become a mess which implementation is injected where.
Another option is to designate one bean as #Primary - it will be preferred to other beans for a given injection point.
Yes, it's possible but not "pretty". You could use a BeanPostProcessor and when you get a bean, check if it's one of your "parent" types and if all its child beans are of the allowable types. Otherwise you can either throw an exception or set those fields to null.

Spring Bean Inheritance - Scope, autowire, depends-on, etc

From Spring documentation http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-child-bean-definitions:
The remaining settings are always taken from the child definition: depends on, autowire mode, dependency check, singleton, scope, lazy init.
I think there is a good reason for not inheriting these settings, but can't think of one. What are the reasons?
I think it's because it would cause more confusion. Imagine the time spent debugging why your bean is not in the default (singleton) scope. Or the case when the child bean is injected into a bean that the parent depends-on. You will get a circular dependency without being able to notice it.
Bean inheritance is only in terms of properties injected, and not in terms of bean settings.
One of the main reasons is that Spring is used to inject implementations. Usually, extended classes are the implementations and it's natural to pick up the configuration details from their definitions.
Other practical reason is that annotations are not inherited. If an interface has annotated methods this annotation is not automatically visible in the implementing/extending classes without some reflection gymnastics.

Resources