I've read that dynamic bean definition change. I try it in a simple code example (see code below), and I find it very attractive in situations where I don't want to stop server but add/change bean definition.
Questions:
Is it safe do to so (see code below)?
I've read that it is possible to achieve bean definition change in runtime with help of StaticApplicationContex or BeanPostProcessor or BeanFactoryPostProcessor? So what is the difference?
public class Main {
final static String header = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<beans xmlns=\"http://www.springframework.org/schema/beans\"\n" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n" +
" xmlns:context=\"http://www.springframework.org/schema/context\"\n" +
" xsi:schemaLocation=\"http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd\">\n" +
" <context:annotation-config />\n" +
" <context:component-scan base-package=\"vbah\"/>";
final static String contextA =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextA\"/>\n" +
"</bean></beans>";
final static String contextB =
"<bean id=\"test\" class=\"java.lang.String\">\n" +
"\t\t<constructor-arg value=\"fromContextB\"/>\n" +
"</bean></beans>";
public static void main(String[] args) throws IOException {
//create a single context file
final File contextFile = new File("src/resources/spring-config.xml");
//write the first context into it
FileUtils.writeStringToFile(contextFile, header + contextA);
//create a spring context
FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext(
new String[]{contextFile.getPath()}
);
//echo "fromContextA"
System.out.println(context.getBean("test"));
//write the second context into it
FileUtils.writeStringToFile(contextFile, header + contextB);
//refresh the context
context.refresh();
//echo "fromContextB"
System.out.println(context.getBean("test"));
}
}
EDIT:
Can you answer the questions below:
As I understand BeanPostProcess allow you to modify already existed bean instances at runtime by wrapping the object with proxy. Am I right?
AbstractApplicationContext#refresh() drop all singleton beans and recreate them.
But If I want to change the definition of prototype/custom scoped bean?
If I've got two beans: A and B. A has reference to B. If I change the bean definition in such way that it doesn't contain definition of B. Than B instances will be destroyed, but new instances won't be created. Than A will get a null dependency. Am I right?
StaticApplicationContext and BeanFactoryPostProcessor both allow me to change a bean definition in runtime. But what are the difference, pros/cons?
[Main question] Why Spring has 3 mechanism to achieve the same goal. Can you make a brief compoarison (or usecases examples) between AbstractApplicationContext#refresh(), StaticApplicationContext and BeanFactoryPostProcessor please.
Is it safe do to so (see code below)?
You'll have to define safe.
The AbstractApplicationContext#refresh() method javadoc states
As this is a startup method, it should destroy already created
singletons if it fails, to avoid dangling resources. In other words,
after invocation of that method, either all or no singletons at all
should be instantiated.
Basically every bean in your context will be destroyed and all references to them will be dropped, making them candidates for garbage collection. You need to make sure that those beans have appropriate ways to release any resources they might have. There are different ways to do that
Make your class implement the DisposableBean interface.
Add a destroy-method attribute to your <bean> or #Bean definition.
Annotate a method with #PreDestroy.
Note that refresh() will typically eagerly refresh your ApplicationContext, ie. re-instantiate all the beans immediately. You may notice some slow down in your application while that happens.
I've read that it is possible to achieve bean definition change in
runtime with help of StaticApplicationContext or BeanPostProcessor or
BeanFactoryPostProcessor? So what is the difference?
StaticApplicationContext is one of the ApplicationContext classes where you register the bean definitions yourself. In your example, the bean definitions are parsed from your XML file and registered behind the scenes. With StaticApplicationContext, you use registerBeanDefinition(..) or the other registerXxx() methods to explicitly register a bean definition.
A BeanFactoryPostProcessor has access to the BeanFactory being used and therefore all the bean definitions that have been registered. As such, you can retrieve any BeanDefinition you want and modify it. As the javadoc for BeanFactoryPostProcess#postProcessBeanFactory(..) states
All bean definitions will have been loaded, but no beans will have
been instantiated yet. This allows for overriding or adding properties
even to eager-initializing beans.
You can change the bean definition before the ApplicationContext actually uses it.
Finally, a BeanPostProcessor doesn't change the bean definition. You can use a BeanPostProcessor to change how a bean is created but the underlying BeanDefinition will stay the same.
For your edit (which is bigger than the actual answer :) )
As I understand BeanPostProcess allow you to modify already existed
bean instances at runtime by wrapping the object with proxy. Am I
right?
It's not just for proxying, you can do anything you want with the object: modify its properties, register it in some other context, make it null, etc. This goes around the bean definition.
AbstractApplicationContext#refresh() drop all singleton beans and
recreate them.
But If I want to change the definition of prototype/custom scoped
bean? If I've got two beans: A and B. A has reference to B. If I
change the bean definition in such way that it doesn't contain
definition of B. Than B instances will be destroyed, but new instances
won't be created. Than A will get a null dependency. Am I right?
In an ApplicationContext, you declare your bean definitions. If you're going to change a bean definition, change it in a BeanFactoryPostProcessor or declare it differently in the context configuration.
For dependencies, if you destroy the B bean definition, there won't be a bean to inject into A and Spring will complain, throwing NoSuchBeanDefinitionException. Bean injection never injects null unless you explicitly tell it to.
StaticApplicationContext and BeanFactoryPostProcessor both allow me to
change a bean definition in runtime. But what are the difference,
pros/cons?
The two serve completely different purposes. StaticApplicationContext is an ApplicationContext implementation. Here, you declare bean definitions. A BeanFactoryPostProcessor serves to modify those bean definitions in any way, based on whatever condition you care to implement.
Why Spring has 3 mechanism to achieve the same goal. Can you make a
brief comparison (or usecases examples) between
AbstractApplicationContext#refresh(), StaticApplicationContext and
BeanFactoryPostProcessor please.
The goal is not the same. An ApplicationContext is different than a BeanFactoryPostProcessor and comes into play at a different time in the context life cycle (see that nice graph you had in a previous question).
I don't have use cases for you. Learn what each of the above can do and you'll know when to apply them when you get specific requirements.
Related
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.
I'm writing a service registry class. This service registry will scan packages for annotated classes and then populate some internal map. What I need then, is to be able to query for services (by String name) using some method (let's say Object get(String name)). This method will then search internal map for a service with such name and returns instance.
What I'm doing right now, is having this ServiceRegistryBean implement ApplicationContextAware and BeanDefinitionRegistryPostProcessor and a list of Strings (package names) given on construct.
Then, as soon as the bean is constructed, registry post processor kicks in (see note) and the registry class adds the service classes as new beans (singleton, lazy loaded) to the spring bean registry. Then, getting the service instance is as simple as requesting a bean from context, returning singleton instance.
My question is: is there a better way in Spring to do this? I've looked into bean factories, but it does not seem to me the same. Support for auto-wiring and DI in service instances is essential, that's why I want Spring to instantiate it. Also, I like the idea of Spring taking care of singletons.
Note: I've found out, that when I inline the bean creation in <constructor-arg> (that is, bean is not named and is just an instance passed as constructor argument of other bean - in my case, I'm passing registry as a parameter to other constructor), BeanDefinitionRegistryPostProcessor interface methods (namely public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)) is not called at all! I'm quite sure, it is some behavior of Spring I don't know about, but I was not able to find proper documentation for the post-processor.
Thank you for any hints or insights!
Scanning for custom annotations it's already supported, you only need to add a include-filter to <context:component-scan> tag, ie
<context:component-scan base-package="org.example">
<context:include-filter type="annotation" expression="some.Annotation"/>
</context:component-scan>
see http://static.springsource.org/spring/docs/current/spring-framework-reference/html/beans.html#beans-scanning-filters
If you turn on default-lazy-init I suppose that the DI Container is ready to use as Service Locator Registry.
About the note, only root bean definitions are taken into account when looking for BeanFactoryPostProcessors, inner beans are ignored.
Usually, scanning and registering beans is done by BeanDefinitionParsers instead because you known when the beans are registered and beans are visible for tools, like STS Spring Bean Explorer, but using a BeanDefinitionRegistryPostProcessor is correct. The interface ensures that beans are defined before other BeanFactoryPostProcessors run.
I've got a name of CDI #Named bean. For example, 'firedEmployeeBean'.
Is there any way in other CDI bean check whether 'firedEmployeeBean' already instantiated or not?
As already stated if you use #Inject once you check it will be. What you instead want is to have a property to tell you what you want:
boolean initiated;
if this simple solution does not cut it I would recommend to use Deltaspike:
MyBean myBean = BeanProvider.getContextualReference(MyBean.class, true);
Note the second argument, true - from docs: Pass true as second argument, if you look for an implementation of the given interface and an implementation isn't required or it isn't required that there is an instance with the given qualifier (see the qualifier example for further details). http://incubator.apache.org/deltaspike/core.html
Lastly you can use events. Events are really simple to use in CDI. What you need to do is fire the event when the bean is created and have the other bean observe that event.
http://docs.jboss.org/weld/reference/latest/en-US/html/events.html
As an alternative, you can use the CDI BeanManager to manually pull up a bean within a given context (or no context at all). Take a JSF context for example, you can use the following snippet to pull all active instances of MyBean within the context.
public void findBean(String beanName, FacesContext facesContext){
BeanManager cdiBeanManager = (BeanManager)((ServletContext) facesContext.getExternalContext().getContext()).getAttribute("javax.enterprise.inject.spi.BeanManager"); //get the BeanManager in your operational context
Bean bean = cdiBeanManager.getBeans(beanName).iterator().next(); //this actually returns a Set, but you're only interested in one
CreationalContext ctx = cdiBeanManager.createCreationalContext(bean);
MyBean theActualBean = cdiBeanManager.getReference(bean, bean.getClass(),ctx); //retrieve the bean from the manager by name. You're guaranteed to retrieve only one of the same name within the given context;
}
This is a pure Java EE implementation, no third party libs
I am confused about the lifecycle of Spring.
XmlBeanFactory beanFactory
= new XmlBeanFactory(new ClassPathResource("SpringHelloWorld.xml"));
Whether the above snippet of codes creates the object or not?
If the above answer is true.
a) Then, for the bean where scope is "singleton" get the object which was created during the above snippet of code. Am i right or wrong?
b) For the case where scope is "prototype", whether the created object was unused. Because, the container always return new object.
XmlBeanFactory beanFactory
= new XmlBeanFactory(new ClassPathResource("SpringHelloWorld.xml"));
Whether the above snippet of codes creates the object or not?
If the answer is false,
How the spring framework validates whether the bean definition is correct or not.
From the answer of Henry
Usually, singleton beans are created when the context starts. This can be changed with the lazy-init or default-lazy-init attributes.
Prototype beans are only created when needed.
Only syntactically, there might still be errors when the bean is instantiated, for example if a required property is not provided.
BeanFactory does not pre-instantiate singletons on startup like ApplicationContext does. So even if your bean is non-lazy and singleton, it won't be created.
prototype beans are created on demand, every time you ask for a prototype bean you'll get a new instance. But once such bean was used during autowiring, the same instance will be used forever.
With ApplicationContext all singletons are created eagerly and prototype beans only on demand.
See also
BeanFactory vs ApplicationContext
Usually, singleton beans are created when the context starts. This can be changed with the lazy-init or default-lazy-init attributes.
Prototype beans are only created when needed.
When you start messing around with Spring's auto-proxy stuff, you often run into this behaviour as documented:
Classes that implement the
BeanPostProcessor interface are
special, and so they are treated
differently by the container. All
BeanPostProcessors and their directly
referenced beans will be instantiated
on startup, as part of the special
startup phase of the
ApplicationContext, then all those
BeanPostProcessors will be registered
in a sorted fashion - and applied to
all further beans. Since AOP
auto-proxying is implemented as a
BeanPostProcessor itself, no
BeanPostProcessors or directly
referenced beans are eligible for
auto-proxying (and thus will not have
aspects 'woven' into them.
For any such bean, you should see an
info log message: “Bean 'foo' is not
eligible for getting processed by all
BeanPostProcessors (for example: not
eligible for auto-proxying)”.
In other words, if I write my own BeanPostProcessor, and that class directly references other beans in the context, then those referenced beans will not be eligible for auto-proxying, and a message is logged to that effect.
My problem is that tracking down where that direct reference is can be very difficult, since the "direct reference" can in fact be a chain of transitive dependencies that ends up taking in half the beans in the application context. All Spring gives you is that single info message, and it's not really much help, beyond telling you when a bean has been caught in this web of references.
The BeanPostProcessor I'm developing does have direct references to other beans, but it's a very limited set of references. Despite this, pretty much every bean in my context is then being excluded from being auto-proxied, according to the log messages, but I can't see where that dependency is happening.
Has anyone found a better way of tracking this down?
Follow this recipe:
Open BeanPostProcessorChecker in your IDE (it's an inner class of AbstractApplicationContext)
Set a breakpoint on if (logger.isInfoEnabled()) { in the method postProcessAfterInitialization
Run your code
When you hit the breakpoint, look for calls to getBean(String,Class<T>) in your stack trace.
One of these calls will try to create a BeanPostProcessor. That bean should be the culprit.
Background
Imagine this situation:
public class FooPP implements BeanPostProcessor {
#Autowire
private Config config;
}
When Spring has to create config (since it's a dependency of FooPP), it has a problem: The contract says that all BeanPostProcessor must be applied to every bean that is being created. But when Spring needs config, there is at least one PP (namely FooPP) which isn't ready for service!
This gets worse when you use an #Configuration class to define this bean:
#Configuration
public class BadSpringConfig {
#Lazy #Bean public Config config() { return new Config(); }
#Lazy #Bean public FooPP fooPP() { return new FooPP(); }
}
Every configuration class is a bean. That means to build a bean factory from BadSpringConfig, Spring needs to apply the post-processor fooPP but in order to do that, it first needs the bean factory ...
In this example, it's possible to break one of the cyclic dependencies. You can make FooPP implement BeanFactoryAware to get Spring inject the BeanFactory into the post processor. That way, you don't need autowiring.
Later in the code, you can lazily ask for the bean:
private LazyInit<Config> helper = new LazyInit<Config>() {
#Override
protected InjectionHelper computeValue() {
return beanFactory.getBean( Config.class );
}
};
#Override
public Object postProcessBeforeInitialization( Object bean, String beanName ) throws BeansException {
String value = helper.get().getConfig(...);
}
(source for LazyInit)
To break the cycle between the bean factory and the post processor, you need to configure the post processor in an XML config file. Spring can read that and build all the structures without getting confused.
Just to bring some closure to this question, the collapse of the uninitialized object graph was caused by the BeanPostProcessor using #Autowired to get its dependencies, and the autowire mechanism effectively caused every other bean definition to be initialized before my BeanPostProcessor got a chance to have a say in the matter. The solution is not to use autowiring for your BPPs.
Not sure if it's of any help, but the Eclipse Spring IDE's
graph view looks like it could be helpful in sorting out bean references..