750 likes | 1.21k Views
Understanding the Bean Lifecycle. An In-depth Look at Spring’s Lifecycle Management Features. Topics in this session. The lifecycle of a Spring application context The initialization phase The use phase The destruction phase Other lifecycle considerations. Topics in this session.
E N D
Understanding the Bean Lifecycle An In-depth Look at Spring’s Lifecycle Management Features
Topics in this session The lifecycle of a Spring application context The initialization phase The use phase The destruction phase Other lifecycle considerations
Topics in this session The lifecycle of a Spring application context The initialization phase The use phase The destruction phase Other lifecycle considerations
Phases of the Application Lifecycle Prepares for use Application services Are created Configured May allocate system resources Application is not usable until this phase is complete Initialization Use Destruction • Used by clients • Application services • Process client requests • Carry out application behaviors • 99.99% of the time is spent in this phase • Shuts down • Application services • Release any system resources • Are eligible for garbage collection
Spring’s Role as a Lifecycle Manager For nearly any class of application Standalone Java application JUnit System Test Java EE™ web application Java EE™ enterprise application Spring fits in to manage the application lifecycle Plays an important role in all phases
The Lifecycle of a Spring Application Context (1) - The Initialization Phase When you create a context the initialization phase completes But exactly what happens in this phase? // Create the application from the configuration ApplicationContext context = new ClassPathXmlApplicationContext(new String[] { “application-config.xml”, “test-infrastructure-config.xml” });
The Context Initialization Lifecycle Load bean definitions Setup standard context services Initialize bean instances
Load Bean Definitions The XML files are parsed Bean definitions are loaded into the context’s BeanFactory Each indexed under its id Special BeanFactoryPostProcessorbeans are invoked Can modify the definition of any bean
Loading Bean Definitions postProcess(BeanFactory) Can modify the definition of any bean in the factory before any objects are created BeanFactoryPostProcessors application-config.xml <beans> <beanid=“transferService” … <beanid=“accountRepository”… </beans> Application Context BeanFactory transferService accountRepository transferService accountRepository dataSource test-infrastructure-config.xml <beans> <beanid=“dataSource” … </beans>
The BeanFactoryPostProcessor Extension Point Useful for applying transformations to groups of bean definitions Before any objects are actually created Several useful ones are already provided in the framework You can also write your own
Useful BeanFactoryPostProcessors provided by Spring PropertyPlaceholderConfigurersubsitutes ${variables} in bean definitions with values from .properties files PropertyOverrideConfigurer overrides default bean definition property values with values in .properties files Explore the BeanFactoryPostProcessor type hierarchy for more
How PropertyPlaceholderConfigurer Works Spring Application Context (after bean definitions are loaded) Bean definition “dataSource” URL=${datasource.url} user=${datasource.user} Bean definition “dataSource” URL=jdbc:oracle:… user=moneytransfer-app postProcess(BeanFactory) PropertyPlaceholderConfigurer
Using PropertyPlaceholderConfigurer Variables to replace File where the variable values reside datasource.properties datasource.url=jdbc:oracle:thin:@localhost:1521:BANK datasource.user=moneytransfer-app Easily editable <beans> <beanid=“dataSource”class=“com.oracle.jdbc.pool.OracleDataSource”> <propertyname=“URL”value=“${datasource.url}”/> <propertyname=“user” value=“${datasource.user}” /> </bean> <beanclass=“org.springframework.beans.factory.config. PropertyPlaceholderConfigurer”> <propertyname=“location”value=“/WEB-INF/datasource.properties”/> </bean> </beans>
Using PropertyOverrideConfigurer Default values File where the default overrides reside datasource.properties dataSource.URL=jdbc:oracle:thin:@localhost:1521:BANK dataSource.user=admin Easily editable <beans> <beanid=“dataSource”class=“com.oracle.jdbc.pool.OracleDataSource”> <propertyname=“URL”value=“jdbc:oracle:thin:@localhost:thin:B”/> <propertyname=“user” value=“moneytransfer-app”/> </bean> <beanclass=“org.springframework.beans.factory.config. PropertyOverrideConfigurer”> <propertyname=“location”value=“/WEB-INF/datasource.properties”/> </bean> </beans>
Implementing Your Own BeanFactoryPostProcessor Implement this interface Configure as a bean (detected automatically) public interface BeanFactoryPostProcessor { void postProcessBeanFactory( ConfigurableListableBeanFactory beanFactory) throws BeansException; } <beans> … <beanclass=“example.EncryptedPropertyDecryptor”/> </beans>
Ordered There may be many BeanFactoryPostProcessors per context Implement the Orderedinterface to order them Remember this as many things in Spring are Ordered <!-- Invoke this one first --> <beanclass=“…PropertyPlaceholderConfigurer”> <propertyname=“order”value=“1”/>… </bean> <!-- Invoke this one second --> <beanclass=“example.EncryptedPropertyValueDecryptor”> <propertyname=“order”value=“2”/> </bean>
Inside the Application Context Initialization Lifecycle Load bean definitions Setup standard context services Initialize bean instances
Setup Standard Context Services A Spring application context sets itself up as a ResourceLoader for loading environmental resources MessageSource for resolving messages ApplicationEventPublisher as an event bus Any bean can obtain a reference to these services when initialized
Standard Application Context Services << interface >> << interface >> << interface >> << interface >> ResourceLoader MessageSource ApplicationEventPublisher ApplicationContext getMessage(String) getResource(String) publishEvent(AppEvent) getBean(String)
The Application Context as a Resource Loader Default resource loading rules depend on the ApplicationContext implementation in use ClassPathXmlApplicationContext defaults to the classpath FileSystemXmlApplicationContext defaults to the filesystem WebApplicationContexts defaults to the web application root directory Use a resource prefix to override the default classpath: - class path resources file:orhttp: - URL resources
Resource Loading Examples Class path context Web application context ClassPathXmlApplicationContext context = … context.getResource(“com/springsource/foo.xml”); context.getResource(“file:/home/rod/image.gif”); context.getResource(“file:working-directory/file.txt”); context.getResource(“http://springsource.com/training/index.html”); WebApplicationContext context = … context.getResource(“/WEB-INF/web.xml”); context.getResource(“classpath:com/springsource/foo.xml”);
Configuring Standard Context Services You may customize several of the other standard context services For example, configure a messageSourceto customize how messages are resolved Common for web applications
Configuring a Message Source <beans> … <beanid=“messageSource” class=“org.springframework.context.support. ReloadableResourceBundleMessageSource”> <propertyname=“basename”value=“/WEB-INF/messages” /> </bean> </beans> Automatically detected by the context Will be automatically injected into beans that need messages
The Context Initialization Lifecycle Load bean definitions Setup standard context services Initialize bean instances
Initialize Bean Instances Each bean is eagerly instantiated by default Created in the right order with its dependencies injected After dependency injection each bean goes through a post-processing phase Where further configuration and initialization can occur After post processing the bean is fully initialized and ready for use Tracked by its id until the context is destroyed
Bean Initialization Steps Bean Instantiated Dependencies Injected Bean Post Processed Bean Ready For Use
Bean Post Processing Bean post processing consists of several steps Configure context services Initialize the bean if instructed Call special BeanPostProcessors to perform additional configuration
Bean Post Processing Steps Configure context services Initialize the bean if instructed Call special BeanPostProcessors to perform additional configuration
Configure Context Services Recall a ApplicationContext is a provider of several services ResourceLoader MessageSource A bean can register itself as a consumer of one or more of these services Spring will automatically inject those services into the bean as part of post processing
Registering for Context Services Register for context services by implementing special “aware” interfaces ResourceLoaderAware for the resource loader MessageSourceAware for the message source ApplicationEventPublisherAware for the event bus ApplicationContextAware for the context itself Useful if your bean needs to access files, resolve messages, publish events, or lookup other beans (respectively)
A ResourceLoaderAware Bean Implements special “aware” interface Spring invokes setter automatically No other configuration required public class BatchFileSender implements ResourceLoaderAware { private ResourceLoader resourceLoader; public voidsetResourceLoader(ResourceLoader rl) { this.resourceLoader = rl; } … } <beans> <beanid=“fileSender”class=“example.BatchFileSender”/> </beans>
A MessageSourceAware Bean Implements special “aware” interface Spring invokes setter automatically No other configuration required public class TransferMoneyAction implements Action, MessageSourceAware { private MessageSource messageSource; public voidsetMessageSource(MessageSouce ms) { this.messageSource = ms; } … } <beans> <beanid=“xferAction”class=“example.TransferMoneyAction”/> </beans>
Bean Post Processing Steps Configure context services Initialize the bean if instructed Call special BeanPostProcessors to perform additional configuration
Initialize the Bean if Instructed A bean can register for one or more initialization callbacks Useful for executing custom initialization behaviors
Registering for an Initialization Callback Register for a bean initialization callback by implementing the InitializingBean interface Spring will invoke this method at the right time public interface InitializingBean { void afterPropertiesSet() throws Exception; }
Implementing InitializingBean Implements special Spring lifecycle interface Spring invokes method automatically No other configuration required public class MessageReceiver implements InitializingBean { public void afterPropertiesSet() { // allocate message receiving resources } } <beans> <beanid=“messageReceiver”class=“example.MessageReceiver” /> </beans>
Initializing a Bean You Do Not Control Use init-method to initialize a bean you do not control the implementation of Class with no Spring dependency Method must be a public with no arguments <beanid=“broker” class=“org.apache.activemq.broker.BrokerService” init-method=“start”> … </bean>
Bean Post Processing Steps Configure context services Initialize the bean if instructed Call special BeanPostProcessors to perform additional configuration
The BeanPostProcessor Extension Point Useful for applying additional configuration to groups of bean instances Powerful enabling feature Several useful ones are already provided in the framework You can also write your own Not that common
How a BeanPostProcessor Works Every BeanPostProcessor gets two callbacks for each bean created by Spring The post processor manipulates the bean instance as it sees fit Can even return a different object in place of the original public interface BeanPostProcessor { Object postProcessBeforeInitialization(Object bean, String beanName); Object postProcessAfterInitialization(Object bean, String beanName); }
Invoking a BeanPostProcessor create inject dependencies initialize bean postProcessBeforeInitialization(Object, String) postProcessAfterInitialization(Object, String) bean (or wrapper) ApplicationContext One of Your Beans BeanPostProcessor
Implementing a BeanPostProcessor public class LogProvidingBeanPostProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) { if (bean instanceof LogAware) { Log log = LogFactory.getLog(bean.getClass()); ((LogAware) bean).setLog(log); } return bean; } public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } } public interface LogAware { void setLog(Log log); }
Configuring a BeanPostProcessor Any bean that implements BeanPostProcessor is detected automatically The callbacks will be invoked as part of the bean instantiation phase <beans> … <beanclass=“example.LogProvidingBeanPostProcessor”/> </beans>
Useful BeanPostProcessors provided by Spring RequiredAnnotationBeanPostProcessorenforces that @Required properties are set A factory that wraps your bean in a proxy to apply additional behaviors Basis for Aspect Oriented Programming (AOP) in Spring Extremely powerful Explore the BeanPostProcessor type hierarchy for more
Using RequiredAnnotationBeanPostProcessor Indicates the dependency is required Automatically detected; no other configuration is necessary public void TransferServiceImpl implements TransferService { private AccountRepository accountRepository; @Required public void setAccountRepository(AccountRepository ar) { this.accountRepository = ar; } } <beans> <beanid=“transferService”class=“example.TransferServiceImpl”/> <beanclass=“org.springframework.beans.factory.annotation. RequiredAnnotationBeanPostProcessor” /> </beans>
The Lifecycle of a Spring Application Context (2) - The Use Phase When you invoke a bean obtained from the context the application is used But exactly what happens in this phase? ApplicationContext context = // get it from somewhere // Lookup the entry point into the application TransferService service = (TransferService) context.getBean(“transferService”); // Use it! service.transfer(new MonetaryAmount(“50.00”), “1”, “2”);
Inside The Bean Request (Use) Lifecycle If the bean is just your raw object it is simply invoked directly (nothing special) If your bean has been wrapped in a proxy things get more interesting TransferServiceImpl TransferServiceImpl transfer(“$50”, “1”, 2”) transfer(“$50”, “1”, 2”) Spring Proxy
Proxy Power Dynamic proxies created by BeanPostProcessors may have added behaviors to your application logic transparently TransferServiceImpl TransactionManager transfer(“$50”, “1”, 2”) Spring TransactionInterceptor begin commit Transaction management behavior is added around your code Spring Proxy
Proxies are Central to the Spring Triangle 2. Dynamic proxies add behaviors to your beans 1. The Application context drives bean configuration 3. Spring can integrate many enterprise behaviors Simple Object Dependency Injection Aspect-Oriented Programming Enterprise Service Abstractions
The Lifecycle of a Spring Application Context (3) - The Destruction Phase When you close a context the destruction phase completes But exactly what happens in this phase? ConfigurableApplicationContext context = … // Destroy the application context.close();