BeanFactory v/s ApplicationContext, explanation through code example [duplicate] - java

I'm pretty new to the Spring Framework, I've been playing around with it and putting a few samples apps together for the purposes of evaluating Spring MVC for use in an upcoming company project. So far I really like what I see in Spring MVC, seems very easy to use and encourages you to write classes that are very unit test-friendly.
Just as an exercise, I'm writing a main method for one of my sample/test projects. One thing I'm unclear about is the exact differences between BeanFactory and ApplicationContext - which is appropriate to use in which conditions?
I understand that ApplicationContext extends BeanFactory, but if I'm just writing a simple main method, do I need the extra functionality that ApplicationContext provides? And just exactly what kind of extra functionality does ApplicationContext provide?
In addition to answering "which should I use in a main() method", are there any standards or guidelines as far as which implementation I should use in such a scenario? Should my main() method be written to depend on the bean/application configuration to be in XML format - is that a safe assumption, or am I locking the user into something specific?
And does this answer change in a web environment - if any of my classes needed to be aware of Spring, are they more likely to need ApplicationContext?
Thanks for any help. I know a lot of these questions are probably answered in the reference manual, but I'm having a hard time finding a clear breakdown of these two interfaces and the pros/cons of each without reading thru the manual with a fine-tooth comb.

The spring docs are great on this: 3.8.1. BeanFactory or ApplicationContext?.
They have a table with a comparison, I'll post a snippet:
Bean Factory
Bean instantiation/wiring
Application Context
Bean instantiation/wiring
Automatic BeanPostProcessor registration
Automatic BeanFactoryPostProcessor registration
Convenient MessageSource access (for i18n)
ApplicationEvent publication
So if you need any of the points presented on the Application Context side, you should use ApplicationContext.

Spring provides two kinds of IOC container, one is XMLBeanFactory and other is ApplicationContext.
BeanFactory
ApplicationContext
Annotation support
No
Yes
BeanPostProcessor Registration
Manual
Automatic
Implementation
XMLBeanFactory
ClassPath/FileSystem/WebXmlApplicationContext
Internationalization
No
Yes
Enterprise services
No
Yes
ApplicationEvent publication
No
Yes
FileSystemXmlApplicationContext Beans loaded through the full path.
ClassPathXmlApplicationContext Beans loaded through the CLASSPATH
XMLWebApplicationContext and AnnotationConfigWebApplicationContext beans loaded through the web application context.
AnnotationConfigApplicationContext Loading Spring beans from Annotation based configuration.
example:
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeansConfiguration.class);
ApplicationContext is the container initialized by a ContextLoaderListener or ContextLoaderServlet defined in a web.xml and ContextLoaderPlugin defined in struts-config.xml.
Note: XmlBeanFactory is deprecated as of Spring 3.1 in favor of DefaultListableBeanFactory and XmlBeanDefinitionReader.

To me, the primary difference to choose BeanFactory over ApplicationContext seems to be that ApplicationContext will pre-instantiate all of the beans. From the Spring docs:
Spring sets properties and resolves dependencies as late as possible, when the bean is actually created. This means that a Spring container which has loaded correctly can later generate an exception when you request an object if there is a problem creating that object or one of its dependencies. For example, the bean throws an exception as a result of a missing or invalid property. This potentially delayed visibility of some configuration issues is why ApplicationContext implementations by default pre-instantiate singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you discover configuration issues when the ApplicationContext is created, not later. You can still override this default behavior so that singleton beans will lazy-initialize, rather than be pre-instantiated.
Given this, I initially chose BeanFactory for use in integration/performance tests since I didn't want to load the entire application for testing isolated beans. However -- and somebody correct me if I'm wrong -- BeanFactory doesn't support classpath XML configuration. So BeanFactory and ApplicationContext each provide a crucial feature I wanted, but neither did both.
Near as I can tell, the note in the documentation about overriding default instantiation behavior takes place in the configuration, and it's per-bean, so I can't just set the "lazy-init" attribute in the XML file or I'm stuck maintaining a version of it for test and one for deployment.
What I ended up doing was extending ClassPathXmlApplicationContext to lazily load beans for use in tests like so:
public class LazyLoadingXmlApplicationContext extends ClassPathXmlApplicationContext {
public LazyLoadingXmlApplicationContext(String[] configLocations) {
super(configLocations);
}
/**
* Upon loading bean definitions, force beans to be lazy-initialized.
* #see org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.xml.XmlBeanDefinitionReader)
*/
#Override
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws IOException {
super.loadBeanDefinitions(reader);
for (String name: reader.getBeanFactory().getBeanDefinitionNames()) {
AbstractBeanDefinition beanDefinition = (AbstractBeanDefinition) reader.getBeanFactory().getBeanDefinition(name);
beanDefinition.setLazyInit(true);
}
}
}

To add onto what Miguel Ping answered, here is another section from the documentation that answers this as well:
Short version: use an ApplicationContext unless you have a really good reason for not doing so. For those of you that are looking for slightly more depth as to the 'but why' of the above recommendation, keep reading.
(posting this for any future Spring novices who might read this question)

ApplicationContext is more preferred way than BeanFactory
In new Spring versions BeanFactory is replaced with ApplicationContext. But still BeanFactory exists for backward compatability
ApplicationContext extends BeanFactory and has the following benefits
it supports internationalization for text messages
it supports event publication to the registered listeners
access to the resources such as URLs and files

ApplicationContext:
It loads spring beans configured in spring configuration file,and manages the life cycle of the spring bean as and WHEN CONTAINER STARTS.It won't wait until getBean("springbeanref") is called.
BeanFactory
It loads spring beans configured in spring configuration file,manages the life cycle of the spring bean when we call the getBean("springbeanref").So when we call the getBean("springbeanref") at the time of spring bean life cycle starts.

I think it's better to always use ApplicationContext, unless you're in a mobile environment like someone else said already. ApplicationContext has more functionality and you definitely want to use the PostProcessors such as RequiredAnnotationBeanPostProcessor, AutowiredAnnotationBeanPostProcessor and CommonAnnotationBeanPostProcessor, which will help you simplify your Spring configuration files, and you can use annotations such as #Required, #PostConstruct, #Resource, etc in your beans.
Even if you don't use all the stuff ApplicationContext offers, it's better to use it anyway, and then later if you decide to use some resource stuff such as messages or post processors, or the other schema to add transactional advices and such, you will already have an ApplicationContext and won't need to change any code.
If you're writing a standalone app, load the ApplicationContext in your main method, using a ClassPathXmlApplicationContext, and get the main bean and invoke its run() (or whatever method) to start your app. If you're writing a web app, use the ContextLoaderListener in web.xml so that it creates the ApplicationContext and you can later get it from the ServletContext, regardless of whether you're using JSP, JSF, JSTL, struts, Tapestry, etc.
Also, remember you can use multiple Spring configuration files and you can either create the ApplicationContext by listing all the files in the constructor (or listing them in the context-param for the ContextLoaderListener), or you can just load a main config file which has import statements. You can import a Spring configuration file into another Spring configuration file by using <import resource="otherfile.xml" /> which is very useful when you programmatically create the ApplicationContext in the main method and load only one Spring config file.

Difference between BeanFactory and ApplicationContext are following:
BeanFactory uses lazy initialization but ApplicationContext uses eager initialization. In case of BeanFactory, bean is created when you call getBeans() method, but bean is created upfront in case of ApplicationContext when the ApplicationContext object is created.
BeanFactory explicitly provide a resource object using syntax but ApplicationContext creates and manages resource objects on its own.
BeanFactory doesnt support internatiolization but ApplicationContext supports internationalization.
With BeanFactory annotation based dependency injection is not supported but annotation based dependency injection is supported in ApplicationContext.
Using BeanFactory:
BeanFactory beanfactory = new XMLBeanFactory(new FileSystemResource("spring.xml"));
Triangle triangle =(Triangle)beanFactory.getBean("triangle");
Using ApplicationContext:
ApplicationContext context = new ClassPathXMLApplicationContext("spring.xml")
Triangle triangle =(Triangle)context.getBean("triangle");

For the most part, ApplicationContext is preferred unless you need to save resources, like on a mobile application.
I'm not sure about depending on XML format, but I'm pretty sure the most common implementations of ApplicationContext are the XML ones such as ClassPathXmlApplicationContext, XmlWebApplicationContext, and FileSystemXmlApplicationContext. Those are the only three I've ever used.
If your developing a web app, it's safe to say you'll need to use XmlWebApplicationContext.
If you want your beans to be aware of Spring, you can have them implement BeanFactoryAware and/or ApplicationContextAware for that, so you can use either BeanFactory or ApplicationContext and choose which interface to implement.

Basically we can create spring container object in two ways
using BeanFactory.
using ApplicationContext.
both are the interfaces,
using implementation classes we can create object for spring container
coming to the differences
BeanFactory :
Does not support the Annotation based dependency Injection.
Doesn't Support I18N.
By default its support Lazy loading.
it doesn't allow configure to multiple configuration files.
ex: BeanFactory context=new XmlBeanFactory(new Resource("applicationContext.xml"));
ApplicationContext
Support Annotation based dependency Injection.-#Autowired, #PreDestroy
Support I18N
Its By default support Aggresive loading.
It allow to configure multiple configuration files.
ex:
ApplicationContext context=new ClasspathXmlApplicationContext("applicationContext.xml");

BeanFactory and ApplicationContext both are ways to get beans from your spring IOC container but still there are some difference.
BeanFactory is the actual container which instantiates, configures, and manages a number of bean's. These beans are typically collaborate with one another, and thus have dependencies between themselves. These dependencies are reflected in the configuration data used by the BeanFactory.
BeanFactory and ApplicationContext both are Java interfaces and ApplicationContext extends BeanFactory. Both of them are configuration using XML configuration files. In short BeanFactory provides basic Inversion of control(IoC) and Dependency Injection (DI) features while ApplicationContext provides advanced features.
A BeanFactory is represented by the interface "org.springframework.beans.factory" Where BeanFactory, for which there are multiple implementations.
ClassPathResource resource = new ClassPathResource("appConfig.xml");
XmlBeanFactory factory = new XmlBeanFactory(resource);
DIFFERENCE
BeanFactory instantiate bean when you call getBean() method while ApplicationContext instantiate Singleton bean when container is started, It doesn't wait for getBean() to be called.
BeanFactory doesn't provide support for internationalization but ApplicationContext provides support for it.
Another difference between BeanFactory vs ApplicationContext is ability to publish event to beans that are registered as listener.
One of the popular implementation of BeanFactory interface is XMLBeanFactory while one of the popular implementation of ApplicationContext interface is ClassPathXmlApplicationContext.
If you are using auto wiring and using BeanFactory than you need to register AutoWiredBeanPostProcessor using API which you can configure in XML if you are using ApplicationContext. In summary BeanFactory is OK for testing and non production use but ApplicationContext is more feature rich container implementation and should be favored over BeanFactory
BeanFactory by default its support Lazy loading and ApplicationContext by default support Aggresive loading.

Feature Matrix of Bean Factory vs Application Context sourced from spring docs
Screenshot of features of BeanFacotry and ApplicationContext

a. One difference between bean factory and application context is that former only instantiate bean when you call getBean() method while ApplicationContext instantiates Singleton bean when the container is started, It doesn't wait for getBean to be called.
b.
ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
or
ApplicationContext context = new ClassPathXmlApplicationContext{"spring_dao.xml","spring_service.xml};
You can use one or more xml file depending on your project requirement. As I am here using two xml files i.e. one for configuration details for service classes other for dao classes. Here ClassPathXmlApplicationContext is child of ApplicationContext.
c. BeanFactory Container is basic container, it can only create objects and inject Dependencies. But we can’t attach other services like security, transaction, messaging etc. to provide all the services we have to use ApplicationContext Container.
d. BeanFactory doesn't provide support for internationalization i.e. i18n but ApplicationContext provides support for it.
e. BeanFactory Container doesn't support the feature of AutoScanning (Support Annotation based dependency Injection), but ApplicationContext Container supports.
f. Beanfactory Container will not create a bean object until the request time. It means Beanfactory Container loads beans lazily. While ApplicationContext Container creates objects of Singleton bean at the time of loading only. It means there is early loading.
g. Beanfactory Container support only two scopes (singleton & prototype) of the beans. But ApplicationContext Container supports all the beans scope.

Refer this doc from Spring Docs:
http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/beans.html#context-introduction-ctx-vs-beanfactory
5.15.1 BeanFactory or ApplicationContext?
Use an ApplicationContext unless you have a good reason for not doing so.
Because the ApplicationContext includes all functionality of the BeanFactory, it is generally recommended over the BeanFactory, except for a few situations such as in an Applet where memory consumption might be critical and a few extra kilobytes might make a difference. However, for most typical enterprise applications and systems, the ApplicationContext is what you will want to use. Spring 2.0 and later makes heavy use of the BeanPostProcessor extension point (to effect proxying and so on). If you use only a plain BeanFactory, a fair amount of support such as transactions and AOP will not take effect, at least not without some extra steps on your part. This situation could be confusing because nothing is actually wrong with the configuration.

ApplicationContext is a big brother of BeanFactory and this would all thing that BeanFactory are provide plus many other things.
In addition to standard org.springframework.beans.factory.BeanFactory lifecycle capabilities, ApplicationContext implementations detect and
invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.

In a real-time scenario, the difference between the Spring IOC Core container (BeanFactory) and Advanced J2EE container (ApplicationContext) are as follows.
BeanFactory will create objects for the beans (i.e., for POJO classes) mentioned in the spring.xml file (<bean></bean>) only when you call the .getBean() method, but whereas ApplicationContext creates the objects for all the beans (<bean></bean> if its scope is not explicitly mentioned as "Prototype") configured in the spring.xml while loading the spring.xml file itself.
BeanFactory: (Lazy container because it creates the objects for the beans only when you explicitly call from the user/main class)
/*
* Using core Container - Lazy container - Because it creates the bean objects On-Demand
*/
//creating a resource
Resource r = (Resource) new ClassPathResource("com.spring.resources/spring.xml");
//creating BeanFactory
BeanFactory factory=new XmlBeanFactory(r);
//Getting the bean for the POJO class "HelloWorld.java"
HelloWorld worldObj1 = (HelloWorld) factory.getBean("test");
ApplicationContext: (Eager container because of creating the objects of all singleton beans while loading the spring.xml file itself)
ApplicationContext context = new ClassPathXmlApplicationContext("com/ioc/constructorDI/resources/spring.xml");
Technically, using ApplicationContext is recommended because in real-time applications, the bean objects will be created while the application is getting started in the server itself. This reduces the response time for the user request as the objects are already available to respond.

I need to explain the BeanFactory & ApplicationContext.
BeanFactory: BeanFactory is root interface for accessing the SpringBean Container.There is basic client view of a bean container.
That interface is implemented by the object class that holds the number of beans definitions, and each uniquely identify by the String name
Depending the Bean definition the factory will return the instance that instance may be the instance of contained object or a single shared instance. Which type of instance will be return depends of bean factory configuration.
Normally Bean factory will load the all the all the beans definition, which stored in the configuration source like XML...etc.
BeanFactory is a simplest container providing the basic support for Dependency Injection
Application Context
Application context is a central interface with in the spring application that provide the configuration information to the application. It implements the Bean Factory Interface.
Application context is an advance container its add advance level of enterprise specific functionality such as ability to resolve the textual message from the property file....etc
An ApplicationContext provides:
Bean factory methods for accessing application components. Inherited from ListableBeanFactory.
The ability to load file resources in a generic fashion. Inherited from the ResourceLoader interface.
The ability to publish events to registered listeners. Inherited from the ApplicationEventPublisher interface.
The ability to resolve messages, supporting internationalization. Inherited from the MessageSource interface.
Inheritance from a parent context. Definitions in a descendant context will always take priority. This means, for example, that a single parent context can be used by an entire web application, while each servlet has its own child context that is independent of that of any other servlet.
In addition to standard BeanFactory lifecycle capabilities, ApplicationContext implementations detect and invoke ApplicationContextAware beans as well as ResourceLoaderAware, ApplicationEventPublisherAware and MessageSourceAware beans.

The BeanFactory means spring container which lazily instantiates bean objects after getBean() method is invoked at runtime.
The ApplicationContext means spring framework which eagerly instantiates bean objects during deployment time without or before invoking getBean() method at runtime.

My six cents:
BeanFactory and ApplicationContext both are interfaces where ApplicationContext extends BeanFactory. So ApplicationContext is a child interface and BeanFactory is the parent interface. In other words, ApplicationContext has all the features of BeanFactory and it has some additional features that are not present in BeanFactory.
BeanFactory loads beans on-demand that is Lazy Loading whereas ApplicationContext loads all beans at startup that is Eager Loading.
BeanFactory does not support annotations whereas ApplicationContext supports annotations.
ApplicationContext has additional features that are not present in BeanFactory: Internationalization, Event Publishing, AOP features.
BeanFactory only supports two scopes — Singleton and Prototype whereas ApplicationContext supports all bean scopes.
BeanFactory does not register BeanFactoryPostProcessor and BeanPostProcessor automatically whereas ApplicationContext automatically registers them.

I think it is worth mentioning that since Spring 3, if you want to create a factory, you can also use the #configuration annotation combined with the proper #scope
#Configuration
public class MyFactory {
#Bean
#Scope("prototype")
public MyClass create() {
return new MyClass();
}
}
Your factory should be visible by Spring container using the #ComponentScan annotation or xml configuration
Spring bean scopes article from baeldung site

do use BeanFactory for non-web applications because it supports only Singleton and Prototype bean-scopes.
While ApplicationContext container does support all the bean-scopes so you should use it for web applications.

In summary:
The ApplicationContext includes all functionality of the BeanFactory.
It is generally recommended to use the former.
There are some limited situations such as in a Mobile application, where memory consumption might be critical.
In that scenarios, It can be justifiable to use the more lightweight BeanFactory. However, in the most enterprise applications, the ApplicationContext is what you will want to use.
For more, see my blog post:
Difference between BeanFactory and ApplicationContext in Spring – The java spring blog from the basics

Related

BeanFactory Vs ApplicationContext in concern of BeanPostProcessor And BeanFactoryPostProcessor

I am now learning little bit detail about Spring IoC Containers with the difference between BeanFactory Vs Application Context. I was also referring the previous stack overflow discussion and tutorial point from the following links,
BeanFactory vs ApplicationContext
https://www.tutorialspoint.com/spring/spring_ioc_containers.htm
In my learning I found that ApplicationContext is capable of resolving textual messages from a properties file and the ability to publish application events to interested event listeners
And BeanPostProcessor Registration and BeanFactoryPostProcessor Registration doing manually in BeanFactory and automatically doing in application context,
So my confusions are,
Since BeanFactory Manually doing BeanPostProcessor registration, Does that mean the developer is doing something while bean is getting initiating ? Because, the same process ApplicationContext does automaticall according to documentations
What is the purpose of BeanFactoryPostProcessor registration ? What is the difference between BeanPostProcessor and BeanFactoryPostProcessor ?
If we say ApplicationContext has the ability to resolving text messages from properties file (Message source access), So for what purpose application context is communicating with property file ?
How can I better understand this concept ?
BeanFactory is lightweight and it doesn't load in-memory/initialize any bean from application.xml (even singleton beans) unless factory.getBean("bean-name") method is called; whereas ApplicationContext is heavyweight is loads everything on container startup. BeanFactory also supports limited scopes like proto and singleton and features like AOP doesn't work with BeanFactory.
So to answer your 1st question YES while using BeanFactory just loading the xml and creating BeanFactory object does not guarantee any bean is initialized; only place to use it is when you are concerned of runtime memory consumption
Note: ApplicationContext extends ListableBeanFactory extends BeanFactory.
BeanPostProcessor as the name suggest gives you hooks to work on an instance of a bean created by the spring container by ApplciationContext/BeanFactory implementation (i.e. before and after initialization) Spring AOPs like transactions. caching etc. ref #Required for example. BeanFactoryPostProcessor on the other end lets you modify the actual bean definition before initialization of the instance. The PropertyResourceConfigurer and PropertyPlaceholderConfigurer are two good examples refer PropertyResourceConfigurer example, how properties are changed before initializing the actual beans.
ApplicationContext main responsibility is initialization of bean, now based on the individual bean is defined it provides way to perform specialized tasks like resources bundle loading/property configurer. I suggest you look at the javadoc for a concrete implementation of ApplicationContext like GenericApplicationContext . If you look at how each methods are implemented you will understand how the control flows from AppContext to individual beans before and after they are initialized. AppContext only has the contract for supports tasks

Spring bean creation lifecycle : Why having multiple interaction points?

I'm learning spring and I'm stuck with the bean lifecycle !
When creating a bean, spring gives us several maners to interact with it. We can use one or all of :
BeanFactoryPostProcessor
BeanPostProcessor#postProcessBeforeInitialization
#PostConstruct
InitializingBean#afterPropertiesSet
#Bean#initMethod
BeanPostProcessor#postProcessAfterInitialization
Spring calls them in the order above
My question is : why all these points of interaction ? and when to use each of them (the use case) ?
A BeanFactoryPostProcessor and a BeanPostProcessor are quite different beast and also apply to different things.
A BeanFactoryPostProcessor will operate on the metadata for a bean (I like to call it the recipe) and will post process that. A well know example is the PropertySourcesPlaceholderConfigurer which will inject/replace all #Value in configuration with the value. A BeanFactoryPostProcessor operates on the metadata and thus before any bean has been created.
The BeanPostProcessor can be applied to a bean and can even replace a bean. Spring AOP uses this quite a lot. An example is the PersistenceExceptionTranslationPostProcessor, when a bean has been created it will pass through this BeanPostProcessor and when it is annotated with #Persistence the bean will be replaced by a proxy. This proxy adds exception translation (i.e. it will convert JpaException and SQLException to the Spring DataAccessException). This is done in a BeanPostProcessor. And can be be done before the init-callbacks are called (the postProcessBeforeInitializationor after they have been called thepostProcessAfterInitialization). The PersistenceExceptionTranslationPostProcessorwill run in thepostProcessAfterInitialization` as it needs to be certain the bean has been initialized.
The ServletContextAwareProcessor will run right after the object has been created to inject the ServletContext as early as possible as the initializing of a bean might depend on it.
The 3 callbacks for initializing a bean are more or less the same but are called in sequence because they have been included in later versions. It starter with only an interface InitializingBean and init-method in xml (later also added to #Bean and the annotation support was added when annotations became a thing.
You need init methods to initialize a bean, you might want to check if all properties have been set (like a required datasource) or you might want to start something. A DataSource (especially a connection pool) is a good example to initialize. After all dependencies have been injected you want to start the pool so it will open the connections. Now as you probably cannot modify the code you want to use the init-method if you control the code you probably want to add #PostConstruct. If you are writing an framework that depends on Spring I would use the InitializingBean.
Next to those 3 init methods you also have the destruction counter-parts. The DisposableBean interface (and destroy-method) and the #PreDestroy annotation. Again when you stop your application you also want to close the connections in your connection pool and you want to probably call the close method on the DataSource. A perfect sample of a destruction callback.

Injecting singletons in to a Spring Boot Application Context

I want to inject some non-Spring managed beans in to a Spring Boot Application. I would have thought the way to do this would be something like:
GenericApplicationContext parentContext = new StaticApplicationContext();
parentContext.getBeanFactory().registerSingleton("pipeline", pipeline);
parentContext.refresh(); // seems to be required sometimes
ApplicationContext context = new SpringApplicationBuilder()
.sources(parentContext)
.child(DispatcherApplication.class)
.run();
However you can only pass in Class<?>... or Object... to the sources method on the builder and in the latter case the only values it recognises are:
Class - A Java class to be loaded by AnnotatedBeanDefinitionReader
Resource - An XML resource to be loaded by XmlBeanDefinitionReader, or a groovy script to be loaded by GroovyBeanDefinitionReader
Package - A Java package to be scanned by ClassPathBeanDefinitionScanner
CharSequence - A class name, resource handle or package name to loaded as appropriate.
So how do I either pass in a parent context instance, or inject singletons in to a Spring Boot application before startup?
TIA
You don't have to create application with your modified context using Application Builder.
Simply make sure you Autowire parentContext and register singleton on the factory derived from it
i couldn't get your parent context approach to work, for more or less the same reason you stated. instead, i:
annotate the bean with #Lazy and #Autowired
create an anonymous ApplicationListener
in the listener call getBeanFactory().registerSingleton()
add the listener to the app with setListener()
here's the stripped-down listener:
public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextRefreshedEvent) {
((GenericApplicationContext) (((ContextRefreshedEvent) event)
.getApplicationContext()))
.getBeanFactory().registerSingleton("legacyBean", obj);
}
}
i didn't find too much documentation on the application lifecycle, but at least most of what i'm doing is standard. however, it does rely on a cast of the context to GenericApplicationContext which "works for me" (Spring Boot 1.4.1) and seems safe, but in theory could change in future versions
my blog post with full source:
http://blog.nqzero.com/2018/01/integrating-spring-with-legacy-app.html

Spring BeanPostProcessor not invoked for all beans?

In an imported spring context XML file I define a bean instance that implements BeanPostProcessor.
In the importing spring context I define a number of beans (using BeanDefinitionBuilder in a custom BeanDefinitionParser).
Not all defined beans are given to the postProcessBeforeInitialization() method on my BeanPostProcessor.
It seems that some other FactoryBeans somehow affect this situation. When looking in the ApplicationContext instance with a debugger I can see all my beans inside - also the ones not being given to the BeanPostProcessor.
How can this happen?

How do you load a bean into Spring MVC's application context?

As I understand it, Spring MVC application has two distinct contexts, the application context and the web context, which are controlled by applicationContext.xml and dispatcher-servlet.xml, respectively.
Inside my controllers, how do I go about loading a bean into either of these contexts?
Note that I am aware of Getting Spring Application Context. That would answer my question for a stand alone application. Where I would use a factory to load the application context from the xml file, but this seems like the wrong way to go about loading beans in Spring MVC.
Matt is absolutely correct. You should not need with any kind of bean-loading/instantiating code in your MVC application, otherwise you're doing something wrong. You define your beans inside the according spring XML configuration files.
<bean id="pinboardServiceTarget" class="com.lifepin.services.PinboardService">
<property name="pinboardEntryDao" ref="pinboardEntryDAO"/>
</bean>
...
<bean id="pinboardEntryDAO" class="com.lifepin.daos.PinboardEntryDAO">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
Your PinboardService class (this is just from an application I wrote recently) will have a property IPinboardEntryDAO like
public class PinboardService implements IPinboardService{
private IPinboardEntryDAO pinboardEntryDao;
...
public void setPinboardEntryDAO(IPinboardEntryDAO dao){
this.pinboardEntryDao = dao;
}
public IPinboardEntryDAO getPinboardEntryDAO(){
...
}
...
}
public class PinboardEntryDAO implements IPinboardEntryDAO{
...
}
Note that inside the the PinboardService class I'm using the DAO interface, not the implementation itself, while in the configuration I'm then injecting the real implementation PinboardEntryDAO. This is a very good practice for separating the different layers (presentation, service and data layer).
Although a Spring MVC application has two distinct contexts, the web context has access to all the beans loaded in the application context. The application context however cannot access beans in the web context. This is used to enforce separation of concerns, e.g. business rules class does not need to know about the HTTP session. So if you have a bean you need access to from both contexts it will have to be declared within the application context.
Any dependencies that your Controller has (such as on service-layer classes, DAOs, etc) should be expressed as normal - through injection, either constructor injection or setter injection.
The context where the controller is mapped just wires it up with any dependencies it needs as normal. The Controller code never needs to work with Spring directly to get any beans, it is wired up with them.
You should use dependency injection and your config files to load beans into your controllers, but if you do need to access the application context directly, any Controller that extends AbstractController (or any of its descendents) has access to the getApplicationContext() method.
In stand alone application we can user context.Refresh() it will reloading/re-instantiating the new requested beans the old beans will have the old instance only.
In web applications we need to overwrite the ContextLoaderListener and call the contextInitialized()
You need to import the file containing the bean definitions of the service layer(say, service-context.xml) into the new project. It can be done as:
<import resource="classpath:service-context.xml"/>

Categories

Resources