I have a spring application where in some cases I need to create an object at runtime, as opposed to a spring injected bean. This object should be created with properties that come from the application context however. If this object is not spring-injected, how can I still take advantage of IoC? Should I make these object properties static and inject them into a bean via non-static setters?
You can still inject properties for object which is not created by spring.
To do that you should use #Configurable annotation. And you should enable LoadTimeWeaving or CompileTimeWeaving. But I think that can be overkill for your situation.
Related
I'm new to Spring and I'm confused about something basic. Are the classes that are stereotyped (Service, Controller, Repository) treated as beans? I'm confused as to when you actually need to annotate/configure something as a bean and when you don't. Is it for the classes that aren't stereotyped?
Thanks!
From spring documentation:
In Spring, the objects that form the backbone of your application and
that are managed by the Spring IoC container are called beans. A bean
is an object that is instantiated, assembled, and otherwise managed by
a Spring IoC container. Otherwise, a bean is simply one of many
objects in your application. Beans, and the dependencies among them,
are reflected in the configuration metadata used by a container.
Service, Controller, Repository are managed by the Spring IoC container, so they are called beans. You annotate a class as #Serivice, #Controller, #Repository, or more in general #Component when you want spring to manage it: spring will manage the instance of annotated class in regard of the scope you select (not all these scope are always available):
singleton – Return a single bean instance per Spring IoC container
prototype – Return a new bean instance each time when requested
request – Return a single bean instance per HTTP request
session – Return a single bean instance per HTTP session
globalSession – Return a single bean instance per global HTTP
session
I'm new to Spring and a little confused about how it works. I get that I can use the application context to instantiate beans and have them populated. However, is the idea that I should be able to just write Bean b = new Bean() and then have Spring to somehow automagically populate that Bean?
I'm experimenting with Spring in a web application, and as far as I can see I need to inject the ApplicationContext into, say, the servlets to be able to instantiate other beans (services, daos etc.) from there. It's a bit cumbersome, but probably works.
However, is Spring meant to be able to hook into any object instantiation which happens on classes defined as beans in applicationContext.xml?
Spring is an Inversion of Control container. A bean is an object whose life cycle is managed by Spring. If you want Spring to populate an object, it needs to go through Spring, ie. it needs to be bean.
is Spring meant to be able to hook into any object instantiation
which happens on classes defined as beans in applicationContext.xml?
Spring doesn't hook into anything. You configure your beans and the relationships between them with Spring and Spring handles creating the instances and linking them up.
For domain objects, Spring provides a solution via the #Configurable annotation: http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#aop-atconfigurable
It requires compile- or load-time-weaving and, thus, introduces some additional complexity but having the convenience of using the standard new Bean() syntax plus Spring's autowiring is worth it in my opinion.
Alternatively, you could define your domain objects as beans with prototype scope and use some factory to create them using the Spring ApplicationContext.getBean() method. With a scope of prototype a new instance will be returned every time and since you go through the ApplicationContext, Spring will do all the dependency injection magic as usual.
As for services and other beans with singleton scope, you would typically NOT retrieve them by first injecting the ApplicationContext and using it but instead you would inject them via either a constructor, setter or annotation-based strategy. The documentation covers that in detail: http://docs.spring.io/spring/docs/4.0.0.RELEASE/spring-framework-reference/htmlsingle/#beans-factory-collaborators
I found out that #PreDestroy only work with singleton scoped bean. I was thinking what could go wrong if we use it with prototype scoped bean. Anything at all??? I dont think so. I think this is just not implemented in spring as they would have to keep the references to all the beans created. Tell me if i am wrong
Spring can only initialize/destroy beans it also controllers and basically prototype scoped beans aren't under the control of spring (after construction). It doesn't know when it is cleaned up, destroyed or what so ever. As such the #PreDestroy method isn't callable for prototype beans (as they do not have a clearly defined lifecycle like singletons or request scoped beans).
For "prototype" scoped beans, Spring does not call the #PreDestroy method.
Here is the answer from the Spring reference manual. Section 7.5.2
http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#beans-factory-scopes-prototype
In contrast to the other scopes, Spring does not manage the complete lifecycle of a
prototype bean: the container instantiates, configures, and otherwise assembles a
prototype object, and hands it to the client, with no further record of that prototype
instance.
Thus, although initialization lifecycle callback methods are called on all objects regardless of scope, in the case of prototypes, configured destruction lifecycle callbacks are not called. The client code must clean up prototype-scoped objects and release expensive resources that the prototype bean(s) are holding.
To get the Spring container to release resources held by prototype-scoped beans, try using a custom bean post-processor, which holds a reference to beans that need to be cleaned up.
The #PreDestroy annotation does not belong to Spring, it’s located in the jsr250-api library jar under javax.annotation package.
By default, Spring will not aware of the #PreDestroy annotation. To enable it, you have to either register CommonAnnotationBeanPostProcessor or specify the <context:annotation-config /> in bean XML configuration file.
If I have a bean defined in an xml file like so :
<bean id="myBean" class="com.myClass">
</bean>
Should "myBean" be autowired, ie should the class "com.myClass" be initialized by Spring ?
I have no Spring annotations in "com.myClass" but the class still seems to be initialized because it is declared in an xml file.
Yes, it is normal that your class to be initialised even though auto-wiring is not stated. The reason for this is:
Declared Spring beans have a life-cycle and the first step in this life-cycle is for Spring to initialise the bean.
The basic life-cycle is as follows:
Initialise Bean
Insert values
Calling certain methods depending on which interfaces you implement. This is useful for further custom initialisation and configuration.
Now your bean is ready for use by your application and will stay in the application context until your application context is destroyed.
Finally, if you implement the DisposableBean interface, the destroy method is called for any de-initialisation process that you may require.
This depends on whether you have any other beans that want Spring to inject myBean into them. If no one uses your bean, you can omit it.
In XML file in spring we have two bean with different id but same class. They have the same properties offcourse. Now I have InitializingBean interface and in afterPropertySet() I am just printing the value of properties.
Its printing the values two times for me?
According Spring Documentation:
afterPropertySet()
Invoked by a BeanFactory after it has set all bean properties supplied (and satisfied BeanFactoryAware and ApplicationContextAware).
So the short answer on your question is: yes
Spring doesn't manipulate classes or object. Spring manipulates Bean Entity. It is the simplest object manipulated by Spring IOC. Bean has additional behaivior rules introduced by Spring.
If you create two beans for example with Singleton scope and not Lazy initializated Spring creates two instances of your class.
Probably you are calling this Class also invoking a Test or by launching a Integration test like this . check the breakpoints , if you are using SpringRunner, try to mock the component