Support destroy method inference

Anywhere the value of a destroy method may be expressed, specifying
the value "(inferred)" now indicates that the container should attempt
to automatically discover a destroy method. This functionality is
currently limited to detecting public, no-arg methods named 'close';
this is particularly useful for commonly used types such as Hibernate
SessionFactory most JDBC DataSource implementations, JMS connection
factories, and so forth.

This special value is captured as the constant
AbstractBeanDefinition#INFER_METHOD, which in turn serves as the default
value of the @Bean#destroyMethod attribute.

For example in the following case

    @Bean
    public BasicDataSource dataSource() { ... }

the container will automatically detect BasicDataSource#close and invoke
it when the enclosing ApplicationContext is closed. This is exactly
equivalent to

    @Bean(destroyMethod="(inferred)")
    public BasicDataSource dataSource() { ... }

A user may override this inference-by-default convention simply by
specifying a different method

    @Bean(destroyMethod="myClose")
    public MyBasicDataSource dataSource() { ... }

or, in the case of a bean that has an otherwise inferrable 'close'
method, but the user wishes to disable handling it entirely, an empty
string may be specified

    @Bean(destroyMethod="")
    public MyBasicDataSource dataSource() { ... }

The special destroy method name "(inferred)" may also be specified in
an XML context, e.g.

    <bean destroy-method="(inferred)">
        or
    <beans default-destroy-method="(inferred)">

Note that "(inferred)" is the default value for @Bean#destroyMethod,
but NOT for the destroy-method and default-destroy-method attributes
in the spring-beans XML schema.

The principal reason for introducing this feature is to avoid forcing
@Configuration class users to type destroyMethod="close" every time a
closeable bean is configured. This kind of boilerplate is easily
forgotten, and this simple convention means the right thing is done
by default, while allowing the user full control over customization or
disablement in special cases.

Issue: SPR-8751
This commit is contained in:
Chris Beams
2011-10-12 02:09:04 +00:00
parent 8cafb7ee13
commit 38e90105a0
6 changed files with 223 additions and 11 deletions

View File

@@ -23,6 +23,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.beans.factory.annotation.Autowire;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
/**
* Indicates that a method produces a bean to be managed by the Spring container. The
@@ -166,16 +167,18 @@ public @interface Bean {
/**
* The optional name of a method to call on the bean instance upon closing the
* application context, for example a {@code close()} method on a {@code DataSource}.
* application context, for example a {@code close()} method on a JDBC {@code
* DataSource} implementation, or a Hibernate {@code SessionFactory} object.
* The method must have no arguments but may throw any exception.
* <p>As a convenience to the user, the container will attempt to infer a destroy
* method based on the return type of the {@code @Bean} method. For example, given a
* method against object returned from the {@code @Bean} method. For example, given a
* {@code @Bean} method returning an Apache Commons DBCP {@code BasicDataSource}, the
* container will notice the {@code close()} method available on that type and
* automatically register it as the {@code destroyMethod}. By contrast, for a return
* type of JDBC {@code DataSource} interface (which does not declare a {@code close()}
* method, no inference is possible and the user must fall back to manually declaring
* {@code @Bean(destroyMethod="close")}.
* container will notice the {@code close()} method available on that object and
* automatically register it as the {@code destroyMethod}. This 'destroy method
* inference' is currently limited to detecting only public, no-arg methods named
* 'close'. The method may be declared at any level of the inheritance hierarchy, and
* will be detected regardless of the return type of the {@code @Bean} method, i.e.
* detection occurs reflectively against the bean instance itself at creation time.
* <p>To disable destroy method inference for a particular {@code @Bean}, specify an
* empty string as the value, e.g. {@code @Bean(destroyMethod="")}.
* <p>Note: Only invoked on beans whose lifecycle is under the full control of the
@@ -183,6 +186,6 @@ public @interface Bean {
* for any other scope.
* @see org.springframework.context.ConfigurableApplicationContext#close()
*/
String destroyMethod() default ConfigurationClassUtils.INFER_METHOD;
String destroyMethod() default AbstractBeanDefinition.INFER_METHOD;
}

View File

@@ -46,8 +46,6 @@ abstract class ConfigurationClassUtils {
private static final String CONFIGURATION_CLASS_ATTRIBUTE =
Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
static final String INFER_METHOD = ""; // TODO SPR-8751 update to '-' or some such
/**
* Check whether the given bean definition is a candidate for a configuration class,