Instantiating a container
Instantiating a Spring IoC container is straightforward. The location path or paths supplied to an ApplicationContext constructor are actually resource strings that allow the container to load configuration metadata from a variety of external resources such as the local file system, from the Java CLASSPATH ,and so on.
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"services.xml","daos.xml"});
Composing XML-based configuration metadata
It can be useful to have bean definitions span multiple XML files.Often each individual XML configuration file represents a logical layer or module in your archirecture.
You can use the application context constructor to load bean definitions from all these XML fragments.This constructor takes multiple Resource locations, as was shown in the previous section.
Alternatively, use one or more occurrences of the element to load bean definitions from anther file or files.For example:
<beans>
<import resource="services.xml"/>
<import resource="resources/messageSource.xml"/>
<import resource="/resource/themeSource.xml"/>
</beans>
You can always use fully qualified resource locations instead of relative paths:for example,”file:C:/config/services.xml”or “calsspath:/config/services.xml”.However ,be aware that you are coupling your application’s configurationm to specific absolute locations.It is generally preferable to keep an indirection for such absolute locations, for example,through”${…}”placeholders that are resolved against JVM system properties at runtime.
你可以使用绝对路径而不是相对路径,例如“file:C:/config/services.xml”或者“classpath:/config/services.xml”.但是你要知道,此时你正在把应用的配置耦合到某个位置。更加通常的情况是使用间接地址例如采用“${}”placeholder 就是会在运行时改变JVM 系统的属性。
Container Extension Points
Typically , an application developer does not need to subclass ApplicationContext implementation classes.Insteda ,the Spring IoC container can be extended by extended by plugging in implementation of special integration interfaces. The next few sections describe these integration interfaces.
Customizing beans using a BeanPostProcessor
The BeanPostProcessor interface defines callback methods that you can implement to provide your own(or override the container’s default)instantiation logic,dependency-resolution logic after the Spring container finishes instantiating,configuring,and initializing a bean, you can plug in one or more BeanPostProcessor implementations.
You can configure multiple BeanPostProcessor instances, and you can control the order in which these BeanPostProcessors execute by setting the order property.You can set this property only if the BeanPostProcessor implements the Ordered interface; if you write your own BeanPostProcessor you should consider implementing the Ordered interface too.For further details , consult the javadocs of the BeanPostProcessor and Ordered interfaces.
Note
BeanPostProcessors operate on bean(or object)instances;that is to say, the Spring IoC container instantiates a bean instance and the BeanPostProcessors do their work.
BeanPostProcessors are scoped per-container.This is only relevant if you are using container hierarchies.If you define a BeanPostProcessor in one container, it will only post-process the beans in that container. In other words, beans that are deined in one container are not post-processed by a BeanPostProcessor defined in another container, even if both containers are part of the same hierarchy.
To chage the actual bean definition(i.e., the bluepring that defines the bean), you instead need to use a BeanFactoryPostProcessor as described in the section called “Customizing configuration metadata with a BeanFactoryPostProcessor”.
The org.springframework.beans.factory.config.BeanPostProcessor interface consists of exactly two callbackmethods.When such a calss is registered as a post-processor with the container,for ecah bean instace that is created by the container, the post-processor gets a callback from the container both before container initializationg methods(such as InitializingBean’s afterPropertiesSet() and any declared init method) are called as well as after any bean initialization callbacks.
BeanPostProcessors and AOP auto-proxying
Classes that implement the BeanPostProcessor interface are special and are treated dirrerently by the container.All BeanPostProcessors and beans that they reference directly are instantiated on startup, as part of the special startup pase of the ApplicationContext.Next , allBeanPostProcessors are registered in a sorted fashion and applied to all further beans in the container.Because AOP auto-proxying is implemented as a BeanPostProcessor itself ,neither BeanPostProcessors nor the beans they reference directly are eligible for auto-proxying , and thus do not have aspects woven into them.
Example:Hello World,BeanPostProcessor-style
This first example illustrates basic usage.The example shows a custom BeanPostProcessor implementation that invokes the toString() method of each brean as it is created by the container and prints the resulting string to the system console.
Find below the custom BeanPostProcessor implementation calss definition:
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.BeansException;
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor{
//simply return the instantiated bean as-is
public Object postProcessBeforeInitialization(Object bean,String beanName)throws BeansException{
return bean;
}
public Object postProcessAfterInitialization(Object bean,String beanName)throws BeansException{
System.out.println("Bean " + beanName + "created : "+bean.toString());
return bean;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/lang
http://www.springframework.org/schema/lang/spring-lang.xsd">
<lang:groovy id="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
<lang:property name="message" value="Fiona Apple Is Just So Dreamy."/>
</lang:groovy>
<!--
when the above bean (messenger) is instantiated, this custom
BeanPostProcessor implementation will output the fact to the system console
-->
<bean class="scripting.InstantiationTracingBeanPostProcessor"/>
</beans>
Notice how the InstantiationTracingBeanPostProcessor is simply defined. It does not even have a name, and because it is a bean it can be dependency-injected just like any other bean.(The preceding configuration also defines a bean that is backed by a Groovy script.The Spring dynamic language support is detailed in the chapter entitled Chapter 34,Dynamic language support).
public final class Boot{
public static void main(final String[] args)throws Exception{
ApplicationContext ctx = new ClassPathXmlApplicationContext("scripting/beans.xml");
Messager messager =(Messager) ctx.getBean("messager");
}
}
Example:The RequiredAnnotationBeanPostProcessor
Using callback interfaces or annotations in conjunction with a custom BeanPostProcessor implementation is a common means of extending the Spring IoC container.An example is Spring’s
RequiredAnnotationBeanPostProcessor -a BeanPostProcessor implementation that ships with the Spring distribution which ensures that JavaBean properties on beans that are marked with an(arbitrary) annotation are actually(configured to be)dependency-injected with a value.
简单来说就是RequiredAnnotationBeanPostProcessor是一个BeanPostProcessor实例,它的功能就是检测Bean上的注解然后,然后对属性进行注入。
Customizing configuration metadata with a BeanFactoryPostProcessor
The next extension point that we will look at is the org.springframework.beans.factory.config.BeanFactoryPostProcessor.The semantics of this interface are similar to hose of the BeanPostProcessor,with one major difference:BeanFactoryPostProcessor operates on the bean configuration metadata; that is , the Spring IoC container allows a BeanFactoryPostProcessor to read the configuration metadata and potentially change it before the container instantiates any beans other than BeanFactoryPostProcessors.