我在春天有一点经验。我想知道Spring上下文/Bean生命周期中回调的数量。我从来没有使用过它们,我可以想象出最需要它们的情况。
,我的问题是:您能为每个回调提供至少一个使用示例吗?意思是当你需要回调的时候。
Conext回调:

Bean回调:

P.S.:
当大多数回调都在调用时,或者编写ApplicationContext的一个或另一个实现是为了什么,这一点对我来说是很清楚的。但我不明白为什么有人想从这个回调\实现中获利。例如:
AbstractRefreshableApplicationContext用于动态更改bean配置。但是为什么呢?在哪种情况下,我可能想要动态更改bean的配置?afterPropertiesSet回调,显然是在设置了所有bean的属性之后调用的:),但是为什么我应该知道这一点,以及何时(可能需要)使用它呢?发布于 2014-01-16 15:08:23
您能为每个回调提供至少一个使用示例吗?
查看每个接口的javadoc,检查实现类的用途,并查找它们的实现源代码。
一个典型的bean定义是
<bean id="someBean" class="com.example.beans.SomeBean">
<property name="someProperty" value="42" />
<property name="other" value="I will always love you." />
</bean>有一个类似的类
public class SomeBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
}但是,有时需要根据属性集执行一些逻辑的类。
public class SomeBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
}只有在设置了属性之后才能执行此逻辑。在这种情况下,您可以让您的类实现InitializingBean接口(旧式)
public class SomeBean implements InitializingBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
public void afterPropertiesSet() throws Exception {
init();
}
}或者用@PostConstruct (新学校)注释它
public class SomeBean implements InitializingBean {
private String someProperty;
private String other;
public void setSomeProperty(String someProperty) {
this.someProperty = someProperty;
}
public void setOther(String other) {
this.other = other;
}
@PostConstruct
public void init() {
Thread thread = new Thread(new Runnable() {
public void run() {
// for example
// send the two property values to some external service
}
});
thread.start();
}
}这只是一个例子。InitializingBean接口通常与FactoryBean接口一起使用。它有助于在工厂生成对象之前初始化它。有关更多的示例,请参阅这两个接口的javadoc,并查找各个实现类的源代码。对其他*Aware接口也这样做。
至于AbstractRefreshableApplicationContext,有时您需要refresh()您的ApplicationContext。这可能是因为您希望重新加载XML配置,或者您的环境已经更改,但是您不希望停止/重新启动应用程序。
发布于 2015-09-29 09:05:37
1. BeanFactoryPostProcessor:
我给出了这个例子,因为我看到了这个答案:https://stackoverflow.com/a/2349891/4251461
他最初选择BeanFactory用于集成/性能测试,因为他不想加载整个应用程序来测试孤立的bean。然而,他认为BeanFactory不支持类路径XML配置。因此,BeanFactory和ApplicationContext都提供了我想要的关键特性,但两者都没有。
他实现了自己的ApplicationContext,它扩展了ClassPathXmlApplicationContext。
在这里,他可以使用BFPP而不是自定义ApplicationContext。
public class LazyInitBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
String[] beanNames = beanFactory.getBeanDefinitionNames();
for (String beanName : beanNames) {
BeanDefinition bd = beanFactory.getBeanDefinition(beanName);
bd.setLazyInit(true);
}
}
}与其他常规bean一样,在spring容器中配置它:
<bean class="com.example.LazyInitBeanFactoryPostProcessor" />您还可以在春季看到PropertyPlaceholderConfigurer和PropertyOverrideConfigurer的来源。
2. InitializingBean:
正如索蒂里奥斯·德里马诺奥利所说: InitializingBean接口经常与FactoryBean接口一起使用。它有助于在工厂生成对象之前初始化它。
下面是一个例子。
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import java.security.MessageDigest;
public class SampleDigesterFactory implements FactoryBean<MessageDigest>, InitializingBean {
MessageDigest messageDigest;
String algorithmName = "MD5";
public MessageDigest getObject() throws Exception {
return messageDigest;
}
public Class<?> getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() throws Exception {
messageDigest = MessageDigest.getInstance(algorithmName);
}
public String getAlgorithmName() {
return algorithmName;
}
public void setAlgorithmName(String algorithmName) {
this.algorithmName = algorithmName;
}
}
import java.security.MessageDigest;
public class SampleDigester {
private MessageDigest messageDigest;
public void digestMessage(String message) {
System.out.println("digest message:" + message);
System.out.println("result: " + messageDigest.digest(message.getBytes()));
}
public MessageDigest getMessageDigest() {
return messageDigest;
}
public void setMessageDigest(MessageDigest messageDigest) {
this.messageDigest = messageDigest;
}
}在spring容器中配置bean:
<bean id="messageDigesterFactoryMD5" class="com.example.SampleDigesterFactory" />
<bean id="messageDigesterFactorySHA1" class="com.example.SampleDigesterFactory" p:algorithmName="SHA1" />
<bean id="sampleDigesterMD5" class="com.example.SampleDigester" p:messageDigest-ref="messageDigesterFactoryMD5" />
<bean id="sampleDigesterSHA1" class="com.example.SampleDigester" p:messageDigest-ref="messageDigesterFactorySHA1" />测试它:
SampleDigester sampleDigesterMD5 = context.getBean("sampleDigesterMD5", SampleDigester.class);
SampleDigester sampleDigesterSHA1 = context.getBean("sampleDigesterSHA1", SampleDigester.class);
sampleDigesterMD5.digestMessage("Hello World!");
sampleDigesterSHA1.digestMessage("Hello World!");产出如下:
文摘信息:你好,世界!
结果:[B@19d02cb ]
文摘信息:你好,世界!
结果:[B@1753b6d ]
春天的推荐信上说:
FactoryBeanconcept和接口在Spring中的许多地方使用;超过50个使用Spring本身的FactoryBeaninterface工具实现。
3. BeanPostProcessor:
您可以参考春季的RequiredAnnotationBeanPostProcessor源。
一个随Spring发行版附带的BeanPostProcessorimplementation,它确保标记为(任意)注释的bean上的JavaBean属性实际上(配置为)依赖--注入一个值。
https://stackoverflow.com/questions/21163355
复制相似问题