Spring4-Container 9-Custom bean Feature

Spring provides several marker interface s that alter the behavior of beans in containers; they include InitializingBean and Disposable bean.The beans implementing both interfaces invoke the lattPropertiesSet() method of the former and the destroy() method of the latter when initializing and destructing.

In modern Spring applications, The JSR-250 @PostConstruct and @PreDestroy interfaces are generally considered best practices for receiving life cycle callbacks.Using these annotations means that the bean s are not coupled to Spring-specific interfaces.See details Section 5.9.7, "@PostConstruct and @PreDestroy".

If you don't want to use JSR-250 annotations, but you're still looking to eliminate coupling, consider using the init and destroy methods of objects to define metadata.

Spring internally uses the BeanPostProcessor implementation to handle any callback interfaces it can find and call the appropriate methods.If you need to customize a feature or lifecycle behavior, you can implement your own BeanPostProcessor.For more information, see Section 5.8, "Container Expansion Points".  

In addition to initialization and destruction callbacks, Spring management objects may also implement the Lifecycle interface, which can participate in container-driven startup and shutdown processes.

The life cycle callback interface is described in this section.

1. Initialize callback function

Implement the org.springframework.beans.factory.InitializingBean interface, which allows the container to perform initialization after all necessary properties of the bean have been set.The InitializingBean interface specifies only one method:

void afterPropertiesSet() throws Exception;

In general, avoid using the InitializingBean interface and discourage it because it will couple code with Spring.Use @PostConstruct Annotate or specify an initialization method for POJO.In the case of XML configuration metadata, the init-method property is used to specify the method name, and the method has no parameter signature.For example, the following definitions:

<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {

    public void init() {
        // do some initialization work
    }

}

The code below is exactly the same as above, but it is not coupled with Spring.

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean {

    public void afterPropertiesSet() {
        // do some initialization work
    }

}

2. Destructive callback function

Implement the org.springframework.beans.factory.DisposableBean interface, allowing a bean to get a callback when the container needs to be destroyed.The DisposableBean interface also specifies only one method:

void destroy() throws Exception;

DisposableBean callback interface is not recommended because it is coupled to Spring.Use @PreDestroy Annotate or specify a common method that can be supported by a bean definition.Based on XML configuration metadata, use the destroy-method property of <bean/>.For example, the following definitions:

<bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
public class ExampleBean {

    public void cleanup() {
        // do some destruction work (like releasing pooled connections)
    }

}

The following code works the same as above, but is not coupled to Spring.

<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements DisposableBean {

    public void destroy() {
        // do some destruction work (like releasing pooled connections)
    }

}

3. Global Initialization and Destruction Methods

The default-init-method and default-destroy-method attributes in the <beans/> element can be used to define a global initialization and destruction method with the following code:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	        http://www.springframework.org/schema/beans/spring-beans.xsd" 
	        default-init-method="init" default-destroy-method="destroy">
</beans>

Be careful:

(1) If you define both global and bean-based initialization methods, only Bean-based initialization and destruction methods will be performed.

(2) The Spring container guarantees that the initial callback of the configuration is performed immediately after all the bean dependencies are satisfied.This means that the initialization callback is called on the native bean, which also means that any such as an AOP interceptor will not be applied at this time.A target bean is created completely before an interceptor chain such as an AOP proxy is applied.Note that if the target bean and the proxy are defined separately, your code can even bypass the proxy to communicate directly with the native bean.Therefore, using interceptors on the initialization method produces unknown results because it binds the target bean to its proxy/interceptor lifecycle and leaves an odd way to communicate directly with the initial bean.

4. Combinatorial Lifecycle Mechanisms

Configure multiple life cycle mechanisms for the same bean, different initialization methods, called as follows:

  • @PostConstruct Meta-comment
  • After PropertiesSet () Definition of InitializingBean
  • Custom init() method

Destroy method calls are in the same order:

  • @PreDestroy Meta-comment
  • destroy() Definition of DisposableBean
  • Custom destroy() method

If there are multiple life cycle mechanism configurations for a bean and each mechanism is configured with a different method name, then all the configured methods will work as described above.However, if the same method name - for example, init() initialization method - is configured with multiple mechanisms, it will only execute once.

4.1 Code Sample

4.1.1 Preparing Bean

package com.ws.edu.spring;

import org.springframework.beans.factory.InitializingBean;
public class Game implements InitializingBean{
	public void init(){
		System.out.println("Game Perform Initialization");
	}
	
	public void init1(){
		System.out.println("Game Execute Initialization 1");
	}
	public void destory(){
		System.out.println("Game Destroy Execution!");
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("Game afterPropertiesSet");
	}
}
package com.ws.edu.spring;

import org.springframework.beans.factory.InitializingBean;

public class Person implements InitializingBean{
	public void init(){
		System.out.println("Person Initialize execution!");
	}
	public void destory(){
		System.out.println("Person Destroy Execution!");
	}
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("Person afterPropertiesSet");
	}
}

4.1.2 Preparing XML

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	        http://www.springframework.org/schema/beans/spring-beans.xsd" default-init-method="init1">
	<bean id="person" class="com.ws.edu.spring.Person" init-method="init" destroy-method="destory"/>
	<bean id="game" class="com.ws.edu.spring.Game" init-method="init" destroy-method="destory"/>
</beans>

4.1.3 Ready to Launch Class

package com.ws.edu.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
		System.out.println(context.getBean(Person.class));
		System.out.println(context.getBean(Game.class));
	}
}

4.1.4 Output Results

Note: @PostConstruct and @PreDestroy annotations only work when annotation scans!

5. Start and close callbacks

The Lifecycle interface defines the basic methods (such as starting and stopping some background processing) for any object that has its own life cycle requirements:

public interface Lifecycle {

    void start();

    void stop();

    boolean isRunning();

}

Any Spring-managed object may implement that interface.Then, when the ApplicationContext starts and stops, it defines all lifecycle implementations of those calls in such a context.Through Lifecycle Processor:

public interface LifecycleProcessor extends Lifecycle {

    void onRefresh();

    void onClose();

}

Lifecycle Processor itself extends to the Lifecycle interface.It also adds two other methods for refreshing and closing contexts.

Ordered calls to start and close are also important.If there is a dependency between any two objects, the relying party will start after the dependency and stop before the dependency.However, sometimes direct dependencies are unknown.You may only know that one type of object should start before another.In this case, the SmartLifecycle interface defines another option, that is, as its superinterface, Phased defines the getPhase() method.

public interface Phased {

    int getPhase();

}
public interface SmartLifecycle extends Lifecycle, Phased {

    boolean isAutoStartup();

    void stop(Runnable callback);

}

The lowest-stage objects start first when they start and end in reverse order.Therefore, the object that implements the SmartLifecycle interface and the getPhase() method with the return value of Integer.MIN_VALUE will stop at the first and last start.On the other hand, the phase value Integer.MAX_VALUE will indicate that the object should stop first and start last (possibly because it depends on other processes running).When considering phase values, it is also important to know that the default phase of any Lifecycle object that does not implement SmartLifecycle is 0.Therefore, any negative values show that an object should start (and stop) before those standard components, and vice versa, any positive values.

As you can see, SmartLifecycle accepts callbacks and defines a stop method.Any implementation must call the callback's run() method after the implementation's shutdown process is complete.That causes asynchronous shutdown, which starts with the default implemented lifecycleProcessor interface, DefaultLifecycleProcessor, waits for its timeout value for the object group in each phase to invoke this callback.The default per-phase timeout is 30 seconds.You can override the default life cycle processor instance by defining a bean named "lifecycle Processor" in the context.If you plan to modify the timeout, then defining the following is sufficient:

<bean id="lifecycleProcessor" class="org.springframework.context.support.DefaultLifecycleProcessor">
    <!-- timeout value in milliseconds -->
    <property name="timeoutPerShutdownPhase" value="10000"/>
</bean>

As mentioned above, the LifecycleProcessor interface defines callback methods for context refresh and shutdown.If `stop() is explicitly called, the latter simply drives the shutdown process, but it occurs when the context is closed.The'refresh'callback is another feature of the `SmartLifecycle' bean on the other hand.When the context is refreshed (after all objects are instantiated and initialized), the callback is invoked, and at this point, the default life cycle processor checks the Boolean value returned by the isAutoStartup() method on each SmartLifecycle object.If "true" is returned, this object will start at this point, rather than waiting for a display call of the context or its own start() method (unlike context refresh, context start does not automatically occur for a standard context).The "phase" value and the "dependent-on" relationship determine the start order in the same way, as described above.

6. Elegantly close the Spring IoC container in non-web applications

This section applies only to non-Web applications.There is already code in the web-based ApplicationContext implementation to handle how to properly close the Spring IoC container when closing a web application.

If you are using Spring's IoC container in a non-web application environment; for example, in a desktop rich client environment, you want the container to close gracefully and call the corresponding destructive callback method on a singleton bean, you need to register a shutdown hook in the JVM.This is very easy to do and will ensure that your Spring IoC container is properly closed and that all resources held by the singleton are released (of course, it is still your job to configure the destroy callback for your singleton and properly implement the destroy callback method).

In order to register the Close Hook, you simply call the registerShutdownHook() method in the AbstractApplicationContext implementation.That is:

import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public final class Boot {

    public static void main(final String[] args) throws Exception {

        AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
                new String []{"beans.xml"});

        // add a shutdown hook for the above context...
        ctx.registerShutdownHook();

        // app runs here...

        // main method exits, hook is called prior to the app shutting down...

    }
}

7 ApplicationContextAware

When a Bean implements the org.springframework.context.ApplicationContextAware interface, the Bean can obtain the ApplicationContext object.

public interface ApplicationContextAware {

    void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

}

Therefore, we can register a Bean manually through the ApplicationContext object programmatically, or expose other functionality by converting references to known subclasses of the interface, such as Configurable ApplicationContext.In general, however, you should avoid it because it couples code to Spring and does not follow Spring-specific rules.

8 BeanNameAware

When a Bean implements the org.springframework.beans.factory.BeanNameAware interface, the Bean can obtain its own identifier defined in the container.

public interface BeanNameAware {

    void setBeanName(string name) throws BeansException;

}

The callback is after all normal bean properties but is called before an initialization callback such as InitializingBean afterPropertiesSet or a custom initialization method.

Keywords: Spring xml encoding jvm

Added by [L3]sPARTAN on Mon, 15 Jul 2019 19:20:29 +0300