Spring Core Technology IOC container (vii)

Source: Internet
Author: User
Tags java format

This article discusses how to extend the bean functionality in spring in the spring life cycle.

Expansion of the container

In general, developers do not need to inherit ApplicationContext to implement their own subclass extension functionality. But the spring IOC container can actually add some functionality by implementing an interface. These interfaces are described below.

Pass BeanPostProcessorDefining beans

BeanPostProcessorInterfaces define callback methods that developers can use to instantiate their own logic, rely on parsing logic, and so on. If the developer just wants to do something in the spring container after the instantiation, configuration and initialization of the bean, it can be done by using it BeanPostProcessor .

Developers can configure multiple BeanPostProcessor instances, and developers can specify the order in which they are executed by configuring the order properties BeanPostProcessor . Of course, you must implement the interface at the same time to configure the order Ordered . If developers write their own BeanPostProcessor , developers should consider implementing the interface at the same time Ordered . If you want to know more information, you can refer to BeanPostProcessor Ordered the Javadoc of the interface.

BeanPostProcessorsis to manipulate the bean instance, in other words, the Spring IOC container must first initialize the bean before it BeanPostProcessors begins to work.
BeanPostProcessorsthe scope of the action is container-based. Of course, it is only when developers use the hierarchy of containers that they need to be considered. If the developer defines one in the container BeanPostProcessor , the instance will only handle the operation after the bean is initialized in the container in which it resides. In other words, a bean in one container is not BeanPostProcessor subsequently processed after initialization, as defined in another container, even if two containers belong to the same container.

org.springframework.beans.factory.config.BeanPostProcessorThe interface consists of 2 callback methods. When an instance of this interface is registered with a container, for each instance created by the container, the post processor gets a call to the callback before the container begins to initialize. The post processor can take any action against the bean instance, including completely ignoring the callback function. The Bean's post processor usually checks the callback interface or wraps the bean with a proxy. Some of the underlying classes, such as the spring AOP Proxy, are implemented by subsequent processors of the bean.

ApplicationContextThe configured beans are automatically checked for implementation of the Beanpostprocessor interface, which ApplicationContext registers the beans as subsequent processors, so that the subsequent processors are called after the Bean is created. The subsequent processor of the bean is managed by the container just like any other bean.

It should be noted that when using annotations on the factory method of the configuration class @Bean , the return value of the factory method should be the implementation class itself, or at least the org.springframework.beans.factory.config.BeanPostProcessor interface, to make it clear that the bean is a post processor. Otherwise, ApplicationContext it is not possible to automatically create this bean when it belongs to the back processor. Because a bean successor processor is required to process the other beans in the container sequentially, the type needs to be checked as early as possible.

Although the spring team recommends a follow-up process for registering beans through ApplicationContext automatic checking, spring also supports programmatic way of passing addBeanPostProcessor methods. This can be useful sometimes, especially if you need to perform some conditional judgment before registering, or when you copy a Bean's successor processor in a structured context. It is important to note that programming is done by BeanPostProcessors ignoring the Ordered interface: The programming registration is BeanPostProcessors always performed before the automatic check-out BeanPostProcessors , and the explicit order definition is ignored.

The container treats those classes that implement the BeanPostProcessor interface in particular. All BeanPostProcessors and the beans they reference are initialized directly at startup as ApplicationContext a special phase of startup. Then, all the BeanPostProcessors beans that are registered and applied sequentially to the container. Because an AOP automatic proxy is BeanPostProcessor implemented by, either BeanPostProcessor it or itself is not an Bean automatic proxy, nor is it injected into the bean. For such a bean, the developer should be aware of the log information similar to info Bean不适合由所有的BeanPostProcessor接口处理 .
It is important to note that once the developer is BeanPostProcessor using automatic loading or @Resource loading the bean,spring may enter undesirable beans through type matching, so that these beans cannot be automatically proxied or subsequently processed. For example, if a developer's bean has an annotated @Resource dependency injection instead of a dependency injection directly through the name attribute, spring will find a matching dependency by type matching.

The following example describes how to write, register, and use BeanPostProcessors .

Example: Hello World BeanPostProcessorWay

The first example illustrates the basic usage. BeanPostProcessorthe custom implementation, shown in the example, invokes the toString() method and prints to the console after the bean is created.

Refer to the following code:

 PackageScriptingImportOrg.springframework.beans.factory.config.BeanPostProcessor;ImportOrg.springframework.beans.BeansException; Public  class instantiationtracingbeanpostprocessor implements beanpostprocessor {     //Simply return the instantiated bean As-is     PublicObjectpostprocessbeforeinitialization(Object Bean, String beanname)throwsbeansexception {returnBean//We could potentially return any object reference here ...} PublicObjectpostprocessafterinitialization(Object Bean, String beanname)throwsbeansexception {System.out.println ("Bean" "+ Beanname +"' Created:"+ bean.tostring ());returnBean }}
<?xml version= "1.0" encoding= "UTF-8"?><beans  xmlns  =< Span class= "Hljs-value" > "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) was instantiated, this custom beanpostprocessor implementation would OUTP UT the fact to the system console --    <Bean class="scripting." Instantiationtracingbeanpostprocessor "/></Beans>

As you can see from the configuration of XML, it InstantiationTracingBeanPostProcessor is simply defined as a bean. It doesn't even have a name, but it's a bean, so you can still do dependency injection.

The following Java application executes the preceding code and configuration:

ImportOrg.springframework.context.ApplicationContext;ImportOrg.springframework.context.support.ClassPathXmlApplicationContext;ImportOrg.springframework.scripting.Messenger; Public Final  class Boot {     Public Static void Main(FinalString[] args)throwsException {ApplicationContext CTX =NewClasspathxmlapplicationcontext ("Scripting/beans.xml"); Messenger Messenger = (Messenger) Ctx.getbean ("Messenger");    System.out.println (Messenger); }}

The output will look similar to the following:

Bean‘messenger‘: org.springframework.scripting.groovy.GroovyMessenger@272961org.springframework.scripting.groovy.GroovyMessenger@272961
Example: RequiredAnnotationBeanPostProcessor

Using callback interfaces or annotations and BeanPostProcessor implementations is common to extend the way of the spring IOC container. One example in spring is the RequiredAnnotationBeanPostProcessor fact that the attribute that is used to ensure that the javabean tag is actually injected into the dependency.

Pass BeanFactoryPostProcessorDefining Configuration Metadata

The next extension is org.springframework.beans.factory.config.BeanFactoryPostProcessor . Semantically, this interface is somewhat similar BeanPostProcessor , but there is a big difference: the BeanFactoryPostProcessor operation Bean Configuration metadata , that is, Spring allows BeanFactoryPostProcessor to read the configuration source data, It is possible to change the configuration metadata before the container instance initializes the session bean.

As mentioned earlier, developers can configure multiple BeanFactoryPostProcessors , and developers can control the order in which they are executed. Of course, the configuration order is an interface that must be implemented Ordered . If you implement your own BeanFactoryPostProcessor , developers should also consider implementing Ordered interfaces. You can BeanFactoryPostProcessor refer Ordered to the Javadoc of the interface to learn more details.

If the developer wants to change the actual bean instance (such as the object created by the configuration metadata), then you need to use it BeanPostProcessor . However, it BeanPostProcessor is possible BeanFactoryPostProcessor to work cooperatively with the bean instance in a technical way (for example, by using a BeanFactory.getBean() function), which causes some immature bean initialization problems and destroys the Standard Life cycle of the container standard. This behavior can lead to negative behavior, such as bypassing the bean's subsequent processing process, and so on. At the same time, the BeanFactoryPostProcessors scope of the action is container-based. Of course it is only relevant when using the container hierarchy. If a developer defines one in a container BeanFactoryPostProcessor , its configuration is only applied to that configured container. The bean definition in another container will not be BeanFactoryPostProcessors processed by subsequent processing, even if two containers are part of the same hierarchy.

When ApplicationContext a subsequent processor is declared in, the subsequent processor of the bean is executed automatically to implement the behavior defined in the configuration. Spring includes a number of pre-defined, well-followed processors that can be used, such as PropertyOverrideConfigurer and PropertyPlaceholderCOnfigurer , to BeanFactoryPostProcessor register custom property editors with custom, for example.

ApplicationContextThe bean that implements the interface in the container is automatically checked BeanFactoryPostProcessor . It is then used as a subsequent processor in the factory when appropriate. Developers can deploy subsequent processors like other beans.

If you use Beanpostprocessor, developers typically do not configure beanfactorypostprocessors to delay initialization. Because if there is no other bean reference Bean(Factory)PostProcessor , then the subsequent processor will not initialize the instance at all. Therefore, delaying the initialization of the configuration will be ignored by spring, and Bean(Factory)PostProcessor will be instantiated regardless of whether the configuration deferred initialization, even if the <beans /> default-lazy-init property is configured as true .

Example: Class name substitution BeanFactoryPostProcessor

Developers use it PropertyPlaceholderConfigurer to Properties materialize the value of a property from a different file using the standard Java format. This class allows developers to deploy applications to different environments using different attributes, such as database URLs or user name passwords, without the need to modify the XML definition.

Refer to the following XML configuration, using DataSource placeholders to define some of the configuration of the database. This example also shows that the configured properties are configured with additional Properties files. At run time, PropertyPlaceholderConfigurer some of the properties that are applied to the metadata will be replaced DataSource . The replacement value, which is the name of the placeholder, is based on the Ant/log4j/JSP EL form of the property configuration.

<beanclass="Org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> < Property name="Locations"Value="Classpath:com/foo/jdbc.properties"/></bean><beanID="DataSource"Destroy-method="Close"        class="Org.apache.commons.dbcp.BasicDataSource"> < Property name="Driverclassname"Value="${jdbc.driverclassname}"/> < Property name="url"Value="${jdbc.url}"/> < Property name="username"Value="${jdbc.username}"/> < Property name="Password"Value="${jdbc.password}"/></bean>

The actual placeholder value is configured in another file, using the Java Properties format, as follows:

jdbc.driverClassName=org.hsqldb.jdbcDriverjdbc.url=jdbc:hsqldb:hsql://production:9002jdbc.username=sajdbc.password=root

As a result, strings are ${jdbc.username} replaced at run time sa , and other placeholders are replaced in turn. The PropertyPlaceholderConfigurer placeholder is checked in the bean definition, and the prefix suffix of the placeholder can be customized.

After Spring 2.5, a context namespace is introduced, and a dedicated configuration element can be used to configure the property placeholder. Multiple addresses can use a comma delimiter.

<context:property-placeholder location="classpath:com/foo/jdbc.properties"/>

PropertyPlaceholderConfigurerNot only the files specified by the developer are viewed Properties . By default, it will still check the Java configuration if it cannot find the attribute in the specified property file System . Developers can systemPropertiesMode modify this behavior by configuring the property, which has the following three values:

    • Nerver (0): Never Check System Properties
    • Fallback (1): If the system property is checked when a specific property is not found from the specified property file, this is the default value.
    • Override (2): First look up system properties before trying to check the specified configuration file. The properties of the system override the properties of the specified file.

You can check out PropertyPlaceholderConfigurer the Javadocs to get more information.

Developers can use PropertyPlaceholderConfigurer alternative class names, which is useful when a particular implementation class needs to be modified.

<Bean class=" Org.springframework.beans.factory.config.PropertyPlaceholderConfigurer ">    < property name="Locations">        <value>Classpath:com/foo/strategy.properties</value>    </Property >    < property name="Properties">        <value>Custom.strategy.class=com.foo.defaultstrategy</value>    </Property ></Bean><bean id="Servicestrategy" class="${custom.strategy.class}" />

If a class cannot be parsed at run time, it will fail when the bean instance is created.

Example: PropertyOverrideConfigurer

PropertyOverrideConfigurer, is another bean's post processor, some similar PropertyPlaceholderConfigurer , but different from the latter, the original definition may have a default value, or there is no value. If the overwritten Properties file does not have an exact bean attribute, the default definition is used.

It is important to note that the bean definition itself is not known to be overwritten, so it is difficult to visualize the configuration being overwritten from the definition of XML. If multiple instances are configured with PropertyOverrideConfigurer different values defined, the last configuration will take effect based on the override mechanism.

The configuration of the properties file is similar to the following:

beanName.property=value

Like what:

dataSource.driverClassName=com.mysql.jdbc.DriverdataSource.url=jdbc:mysql:mydb

The above instance file, which can be used for a bean named DataSource, contains the properties of the driver and the URL.

The composite accessory name is also supported, but requires that the components on each path need to be non-null, such as:

foo.fred.bob.sammy=123

The specified overridden value is always literal, and cannot be another bean dependency, and this Convention is applied to the case where the original value refers specifically to the bean reference.

In the namespaces introduced in Spring 2.5 context , you can also specify that the configuration overrides the file attributes as follows:

<context:property-override location="classpath:override.properties"/>
Custom FactoryBeanThe initialization logic

Some objects themselves are similar to factories that can be considered to implement org.springframework.beans.factory.FactoryBean interfaces.

FactoryBeanAn interface is a plug-in logic similar to a spring IOC container. If the developer's code has complex initialization code and the Java code in the configuration is more efficient than XML, developers can consider creating their own FacotoryBean objects, putting complex initialization operations into the class, and extending the customizations FactoryBean to the container.

FacotryBeanThe interface provides the following three methods:

    • Object getObject(): Returns an object created by a factory. Instances can be shared, depending on whether the scope of the returned Bean is a prototype or a singleton.
    • boolean isSingleton(): If a singleton is returned, the FactoryBean TrueFalse
    • Class getObjectType(): Returns getObject() the type of the object returned by the method, or null if the object type is unknown.

FactoryBeanThe concepts and interfaces are widely used in the pre-spring framework, and spring itself has more than 50 FactoryBean implementations.

When a developer needs an FactoryBean instance instead of the bean it produces, the method that is called is preceded by a ApplicationContext getBean() symbol before its ID & . That is, for a given FactoryBean , whose ID is called, the call returns the myBean getBean("myBean") Bean Object It produces, and the call getBean("&myBean") returns the FactoryBean instance itself.

Spring Core Technology IOC container (vii)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.