我在Spring有一点经验。我想知道Spring Context / Bean Lifecycle中的回调量。我从来没有使用它们,并且可以成像需要大部分的情况。
我的问题是 :您是否可以为每个回调提供至少一个使用示例?表示您需要回调时的情况。< / p>
Conext回调:
Bean回调:
P.S:
当大多数回调调用时,或者为ApplicationContext编写了一个或另一个实现时,很明显。但我无法弄清楚为什么有人可能想要从回调\实施中获利。例如:
AbstractRefreshableApplicationContext
用于在飞行中更改bean配置。但为什么?在哪种情况下,我可能想在飞行中更改bean的配置?afterPropertiesSet
回调,显然是在设置了所有bean的属性后调用的:)但为什么我应该知道这一点,何时应该(可能想要)使用它?答案 0 :(得分:4)
你能为每个回调提供至少一个使用示例吗?
查看每个接口的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配置,或者因为您的环境已更改,但您不想停止/重新启动应用程序。
答案 1 :(得分:0)
<强> 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:强>
正如Sotirios Delimanolis所说: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!");
输出结果为:
摘要信息:Hello World!
结果:[B @ 19d02cb
消化信息:Hello World!
结果:[B @ 1753b6d
春季参考文献说:
FactoryBeanconcept和接口在Spring Framework中的许多地方使用; FactoryBeaninterface的50多个实现随Spring一起提供。
第3。的BeanPostProcessor:强>
您可以在spring中引用RequiredAnnotationBeanPostProcessor的源代码。
与Spring发行版一起提供的BeanPostProcessorimplementation,它确保使用(任意)注释标记的bean上的JavaBean属性实际上(配置为)依赖注入值。