spring扩展点整理

背景

Spring的强大和灵活性不用再强调了。而灵活性就是通过一系列的扩展点来实现的,这些扩展点给应用程序提供了参与Spring容器创建的过程,好多定制化的东西都需要扩展点的支持。尤其在使用SpringBoot的过程中。

BeanFactoryPostProcessor

这个扩展点是以一个接口定义的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/**
* Allows for custom modification of an application context's bean definitions,
* adapting the bean property values of the context's underlying bean factory.
*
* <p>Application contexts can auto-detect BeanFactoryPostProcessor beans in
* their bean definitions and apply them before any other beans get created.
*
* <p>Useful for custom config files targeted at system administrators that
* override bean properties configured in the application context.
*
* <p>See PropertyResourceConfigurer and its concrete implementations
* for out-of-the-box solutions that address such configuration needs.
*
* <p>A BeanFactoryPostProcessor may interact with and modify bean
* definitions, but never bean instances. Doing so may cause premature bean
* instantiation, violating the container and causing unintended side-effects.
* If bean instance interaction is required, consider implementing
* {@link BeanPostProcessor} instead.
*
* @author Juergen Hoeller
* @since 06.07.2003
* @see BeanPostProcessor
* @see PropertyResourceConfigurer
*/
public interface BeanFactoryPostProcessor {

/**
* Modify the application context's internal bean factory after its standard
* initialization. All bean definitions will have been loaded, but no beans
* will have been instantiated yet. This allows for overriding or adding
* properties even to eager-initializing beans.
* @param beanFactory the bean factory used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}

BeanFactoryPostProcessor 这个扩展点的功能是:让应用程序在Spring创建Bean对象前修改BeanDefinition。其中一个例子就是Bean属性配置的类型转换,占位符替换。

BeanDefinitionRegistryPostProcessor

该扩展点的定义如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* Extension to the standard {@link BeanFactoryPostProcessor} SPI, allowing for
* the registration of further bean definitions <i>before</i> regular
* BeanFactoryPostProcessor detection kicks in. In particular,
* BeanDefinitionRegistryPostProcessor may register further bean definitions
* which in turn define BeanFactoryPostProcessor instances.
*
* @author Juergen Hoeller
* @since 3.0.1
* @see org.springframework.context.annotation.ConfigurationClassPostProcessor
*/
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {

true/**
* Modify the application context's internal bean definition registry after its
* standard initialization. All regular bean definitions will have been loaded,
* but no beans will have been instantiated yet. This allows for adding further
* bean definitions before the next post-processing phase kicks in.
* @param registry the bean definition registry used by the application context
* @throws org.springframework.beans.BeansException in case of errors
*/
truevoid postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;

}

如上面的注释说明:该扩展点可以让应用程序注册自定义的BeanDefinition,并且该扩展点在 BeanFactoryPostProcessor 前执行。

Aware

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* Marker superinterface indicating that a bean is eligible to be
* notified by the Spring container of a particular framework object
* through a callback-style method. Actual method signature is
* determined by individual subinterfaces, but should typically
* consist of just one void-returning method that accepts a single
* argument.
*
* <p>Note that merely implementing {@link Aware} provides no default
* functionality. Rather, processing must be done explicitly, for example
* in a {@link org.springframework.beans.factory.config.BeanPostProcessor BeanPostProcessor}.
* Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
* and {@link org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory}
* for examples of processing {@code *Aware} interface callbacks.
*
* @author Chris Beams
* @since 3.1
*/
public interface Aware {

}

Aware 接口是一个标记接口,表示所有实现该接口的类是会被Spring容器选中,并得到某种通知。所有该接口的子接口提供固定的接收通知的方法。这样的接口有很多,最常用的如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public interface ApplicationContextAware extends Aware {
true/**
* Set the ApplicationContext that this object runs in.
* Normally this call will be used to initialize the object.
* <p>Invoked after population of normal bean properties but before an init callback such
* as {@link org.springframework.beans.factory.InitializingBean#afterPropertiesSet()}
* or a custom init-method. Invoked after {@link ResourceLoaderAware#setResourceLoader},
* {@link ApplicationEventPublisherAware#setApplicationEventPublisher} and
* {@link MessageSourceAware}, if applicable.
* @param applicationContext the ApplicationContext object to be used by this object
* @throws ApplicationContextException in case of context initialization errors
* @throws BeansException if thrown by application context methods
* @see org.springframework.beans.factory.BeanInitializationException
*/
truevoid setApplicationContext(ApplicationContext applicationContext) throws BeansException;
}

ApplicationContextAware的回调方法是在一般的属性注入后,但没有执行Bean的初始化方法前被执行的。初始化方法包括init-methodInitializingBeanafterPropertiesSet方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Interface to be implemented by any bean that wishes to be notified
* of the {@link Environment} that it runs in.
*
* @author Chris Beams
* @since 3.1
*/
public interface EnvironmentAware extends Aware {
true/**
* Set the {@code Environment} that this object runs in.
*/
truevoid setEnvironment(Environment environment);
}

该接口用来接收应用程序的运行环境对象。

ApplicationListener

1
2
3
4
5
6
7
8
9
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

true/**
* Handle an application event.
* @param event the event to respond to
*/
truevoid onApplicationEvent(E event);

}

ApplicationListener 接口主要用来监听应用程序上下文的事件,不同的实现子类注册自己感兴趣的事件。

InitializingBean

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public interface InitializingBean {

true/**
* Invoked by a BeanFactory after it has set all bean properties supplied
* (and satisfied BeanFactoryAware and ApplicationContextAware).
* <p>This method allows the bean instance to perform initialization only
* possible when all bean properties have been set and to throw an
* exception in the event of misconfiguration.
* @throws Exception in the event of misconfiguration (such
* as failure to set an essential property) or if initialization fails.
*/
truevoid afterPropertiesSet() throws Exception;

}

InitializingBean 主要用来实现自定义的Bean初始化逻辑。 InitializingBean接口的方法会被BeanFactory在BeanFactoryAware或ApplicationContextAware接口方法调用后进行调用。

InitializingBean 接口的功能还有一个替代方式,就是在xml配置bean结点属性的init-method属性,指定初始化方法。需要注意的时候如同同时实现了InitializingBean接口并且配置了init-method属性,则InitializingBean接口的方法会被先执行。

BeanPostProcessor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public interface BeanPostProcessor {

true/**
* Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
*/
trueObject postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;

true/**
* Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
* initialization callbacks (like InitializingBean's {@code afterPropertiesSet}
* or a custom init-method). The bean will already be populated with property values.
* The returned bean instance may be a wrapper around the original.
* <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
* instance and the objects created by the FactoryBean (as of Spring 2.0). The
* post-processor can decide whether to apply to either the FactoryBean or created
* objects or both through corresponding {@code bean instanceof FactoryBean} checks.
* <p>This callback will also be invoked after a short-circuiting triggered by a
* {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
* in contrast to all other BeanPostProcessor callbacks.
* @param bean the new bean instance
* @param beanName the name of the bean
* @return the bean instance to use, either the original or a wrapped one;
* if {@code null}, no subsequent BeanPostProcessors will be invoked
* @throws org.springframework.beans.BeansException in case of errors
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
* @see org.springframework.beans.factory.FactoryBean
*/
trueObject postProcessAfterInitialization(Object bean, String beanName) throws BeansException;

}

BeanPostProcessor 接口定义了在bean初始化前和初始化后执行的方法。应用程序自己可以实现该接口定义自己特殊的逻辑。

参考:http://jinnianshilongnian.iteye.com/blog/1489787http://jinnianshilongnian.iteye.com/blog/1492424

FactoryBean

1
2
3
4
5
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}

通过实现接口FactoryBean来自定义Bean的创建逻辑。Spring容器对待实现了接口FactoryBean的类是特殊处理的。当你需要向容器请求一个真实的FactoryBean实例,而不是它生产的bean,例如调用ApplicationContextgetBean()方法时,在beanid之前要有连字符(&)。对于一个给定 idmyBeanFactoryBean,调用容器的getBean("myBean")方法返回的FactoryBean产品。

文章目录
  1. 1. 背景
  2. 2. BeanFactoryPostProcessor
  3. 3. BeanDefinitionRegistryPostProcessor
  4. 4. Aware
  5. 5. ApplicationListener
  6. 6. InitializingBean
  7. 7. BeanPostProcessor
  8. 8. FactoryBean
|