How can i remove a singleton spring bean from ApplicationContext? - spring

I want to develop a module control system so that every spring bean can be managed by my own LifeCycle Controller.
But I can not figure out how can I remove a singleton spring bean out of ApplicationContext.
That may be an interesting problem , can you help me to resolve ?

Removing definition does both : removing definition and destroying (removing all container references on that bean) corresponding Singleton :
((BeanDefinitionRegistry) beanFactory).removeBeanDefinition("myBean");
If you just need to remove the singleton then :
((DefaultListableBeanFactory) beanFactory).destroySingleton("myBean");
The latter way may be especially useful if you just registered singleton but haven't defined any bean definitions, i.e.
((SingletonBeanRegistry) beanFactory).registerSingleton("myBean", myBeanInstance);

You can try removing the bean definition. Get the BeanDefinitionRegistry and call removeDefinition(..)
It depends on the way you create your application, but for example in web application you can get the definition registry by:
BeanDefinitionRegistry factory =
(BeanDefinitionRegistry) applicationCtx.getAutowireCapableBeanFactory();
(the bean factory implements BeanDefinitionRegistry).
I don't know if the bean instance will be removed as well. Give it a try.

Related

AnnotationConfigApplicationContext parameters

When I create the context:
new AnnotationConfigApplicationContext(SpringApp.class);
where SpringApp is not annotated neither with #Configuration nor with anything else.
I'm getting the springApp bean anyway.
Why? The documentation says
Create a new AnnotationConfigApplicationContext, deriving bean
definitions from the given annotated classes and automatically
refreshing the context.
So I can't understand why springApp bean is created if there are no annotations there.
Your confusion is legit. Spring does not handle the SpringApp.class as a Configuration but respects it's deriving bean-definitions. The Spring-App-Instnce is of scope singleton.
From the documentation:
(red:the Constructor) Create a new AnnotationConfigApplicationContext, deriving bean definitions from the given annotated classes and automatically refreshing the context.

Confuse of Spring Xml config bean and Annotation config bean

Lately I am confused about 1 thing.
I defined PlaceHolderConfigurer in applicationContext.xml and config 1 bean in applicationContext.xml too, for example it's called myService which has a property: name I inject value with #Value($env{name}).
And this bean is also annotated with #Service annotation, then I add <Component-scan.....> in dispatch-servlet.xml.
I thought the property: name doesn't get value, because Xml bean is overridden by component scan bean andPlaceHolderConfigurer can't be shared between application context and dispatch servlet context, but actually it have value which I configured in property file.
So is there anyone can explain a little bit for me?
Anything will be appreciated. Thanks
You created two versions of one bean - one defined in applicationContext and one in dispatcherServlet. That usually wrong.
As you suggest PlaceHolderConfigurer not shared beetween parent/child context. It works only for context where it defined.

Spring FactoryBean used before it is configured?

I have two FactoryBeans creating proxies for existing beans in the application context.
FactoryBeanA.getObject() is invoked as part of the singleton pre-instantiation, and it attempts to autowire the returned instance.
This autowiring needs a bean that is defined by FactoryBeanB, which has not yet been configured (had properties injected).
Can this be controlled in such a way, that I am sure both FactoryBeans are fully configured (properties injected) before any beans are attempted instantiated?
Edit:
Autowiring from FactoryBeanA objects have worked fine until I changed FactoryBeanB to require a property to be injected. After this change, I see autowiring for the A-bean try to invoke FactoryBeanB.getObject(), but this fails as properties has not yet been injected.
Problem was actually caused by my own mistake. FactoryBeanB was not configured properly as I thought.

injecting spring beans into non-singleton classes

is it possible to inject spring beans into a polling filter class (FClass) controlled by a scheduler job?
i don't quite understand how singleton applies here.
i understand spring beans are singleton so in order to inject the spring beans into class FClass. i need to define FClass as a bean and add the DI as property etc..
so how do i know if FClass should be a singleton? i assume only classes that are singletons can be created and beans and have DI done to them.
my problem is :
i need to be able to inject my facade bean xfacade into FClass. x_facacde handles the dao object. it has Y_dao and a Z_hibernate session beans injected as DI.
when i tried to create a spring bean of StatusPollingFilter (FClass) and injected the facade bean - i got a null and the setter is never called for the injection in debug mode.
the problem:
i'm thought it might be something to do with the thread / scheduler nature of StatusPollingFilter, and since spring beans are singletons it might not work due to that.
i'm thinking of creating a factory for the StatusPollingFilter (FClass). but need to know if this is correct thing and i'm on right track before i do too much work and realize even that doesn't work as the problem might be somewhere else. ideally i just want to update a table in the easiest possible way. but i have to use hibernate as the DAO exists but hibernate is configured using
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
with /hibernate/TopoObject.hbm.xml
files.
so no matter how i try this i always get null pointer exception on session or injected facade bean.
reading some of the QA's here seems like because StatusPollingFilter is instantiated using the scheduler and not spring it cant be aware of the DI beans. so would the above factory pattern help here.
I may have an additional problem but i'll cross that bridge when i come to it. but just to mention briefly, in case anyone is aware of issues that i might hit ... not sure what / how the scheduler would invoke the factory for an instance as its all controlled by 3rd party api - which invokes a StatusPollingFilter but i'm assuming if i pass in the factory as the class and parameter it would find its way through... but initial part is the main question. please ignore the latter waffle. thanks in advance.
Actually :
i assume only classes that are singletons can be created
is where you are wrong.
A bean is just a class that you let spring instantiate. By default, they are created as singleton but you can specify the scope on your bean using the attribute scope (quite surprisingly). The value you can specify are those specified in the documentation here
So one thing you have to be careful with is the injection of beans scoped as prototype or request into singletons.
having read more - i have come across the ans.
because the StatusPollingFilter object is under control of scheduler (i knew that scheduler had something to do with it) then it is unaware of the spring beans which is why i keep getting null when i try injecting the bean.
i created a class:
ApplicationContextProvider implements ApplicationContextAware
added static access
private static ApplicationContext appContext;
did a setter for it :
public void setApplicationContext(ApplicationContext context)
{
appContext = context;
}
and added
public static Object getBean(String beanName) throws BeansException
{
return appContext.getBean(beanName);
}
used in code as :
EvoTAMDAOFacade evoDao = (EvoTAMDAOFacade) ApplicationContextProvider.getBean("evoDaoFacade");
i now have access to the facade bean and all injected beans into facade.
i still have an issue with hibernate session but thats prob due to some other issue.
pt here is i don't have access to the bean as its not in control of the spring container so i needed to somehow get it , probably could have done it via the factory method but why mess around when there a simpler way.
thanks for help by anyone who may have posted or tried to understand my problem.

Spring Standard Bean Injection vs. Autowiring

As far as I understand When Using Dependency Injection all bean are initializing on Start.
<bean id="userPreferences" class="com.foo.UserPreferences">
</bean>
<!-- a singleton-scoped bean injected to the above bean -->
<bean id="userService" class="com.foo.SimpleUserService">
<!-- a reference to the userPreferences bean -->
<property name="userPreferences" ref="userPreferences"/>
</bean>
and the configuration above means that userService and userPreferences created when application starts. Is it correct?
When using Autowiring and using <context:component-scan>
public class SimpleUserService{
#Autowired
UserPreferences userPreferences;
//omitted
}
1) Is userPreference created on Application init?
2) What is the default scope for bean injected by autowire and how can we change it?
3) How affects bean creation and bean injection?
Hope I made myself clear.
First of all you should add #Service or #Component to the SimpleUserService class.
1 Yes, the ONE instance of UserPreferences is created at application intialization
2 Default scope is singleton, You can change it with the #Scope annotation (#See Spring Reference: 3.11.4.4 Specifying bean scope)
3 Component scan and XML configuration work in the same way (life cycle)
Maybe you should spend some time in understanding the Spring life cycle. You need to understand that Spring works a bit in this way (not 100% correct):
first it creates a pool of beans
then it injects the properties into the beans
But it does NOT work this way: taking a class, look what references it needs creating this references (recursive) and then creating the class.
If you understand this, then you will also understand, that the #Scope of a bean is defined at the bean declaration/class, but not at the references.
1) Is userPreference created on
Application init?
In either case userPreferences is initialized when Spring Context is loaded. You can change this behavior by adding lazy-init="true" to the bean configuration.
2) What is the default scope for bean
injected by autowire and how can we
change it?
The scope of what is injected is all beans loaded into Spring. If you import an XML configuration from another project, it too would be included. I'm not sure if you can limit your scope.
3) How affects bean creation and bean
injection?
Whether is autowired, or configured via XML, the behavior should be the same. I prefer explicitly defining dependencies over automatic annotations. Then again I also like strongly typed languages.
the configuration above means that userService and userPreferences created when application starts. Is it correct?
Yes
Is userPreference created on Application init?
Yes
What is the default scope for bean injected by autowire and how can we change it?
The default scope is always "singleton". This can be changed either using #Scope with #Bean or the scope XML attribute on <bean>.
How affects bean creation and bean injection?
This isn't a clear question. If you change the bean scope, you change when it gets created (start of application, on each request, on each session, etc). The wiring configuration remains the same, only the lifecycle changes.
The #autowired notation is an obsolete way to say #inject. THe latter is a feature of JavaEE 6.
stackoverflow.com/questions/7142622/what-is-the-difference-between-inject-and-autowired-in-spring-framework-which

Resources