首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Spring上下文和Bean生命周期回调:使用实例

Spring上下文和Bean生命周期回调:使用实例
EN

Stack Overflow用户
提问于 2014-01-16 13:38:12
回答 2查看 8.4K关注 0票数 6

我在春天有一点经验。我想知道Spring上下文/Bean生命周期中回调的数量。我从来没有使用过它们,我可以想象出最需要它们的情况。

,我的问题是:您能为每个回调提供至少一个使用示例吗?意思是当你需要回调的时候。

Conext回调:

Bean回调:

P.S.:

当大多数回调都在调用时,或者编写ApplicationContext的一个或另一个实现是为了什么,这一点对我来说是很清楚的。但我不明白为什么有人想从这个回调\实现中获利。例如:

  • AbstractRefreshableApplicationContext用于动态更改bean配置。但是为什么呢?在哪种情况下,我可能想要动态更改bean的配置?
  • afterPropertiesSet回调,显然是在设置了所有bean的属性之后调用的:),但是为什么我应该知道这一点,以及何时(可能需要)使用它呢?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-01-16 15:08:23

您能为每个回调提供至少一个使用示例吗?

查看每个接口的javadoc,检查实现类的用途,并查找它们的实现源代码。

一个典型的bean定义是

代码语言:javascript
复制
<bean id="someBean" class="com.example.beans.SomeBean">
    <property name="someProperty" value="42" />
    <property name="other" value="I will always love you." />
</bean>

有一个类似的类

代码语言:javascript
复制
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;
    }
}

但是,有时需要根据属性集执行一些逻辑的类。

代码语言:javascript
复制
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接口(旧式)

代码语言:javascript
复制
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 (新学校)注释它

代码语言:javascript
复制
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配置,或者您的环境已经更改,但是您不希望停止/重新启动应用程序。

票数 5
EN

Stack Overflow用户

发布于 2015-09-29 09:05:37

1. BeanFactoryPostProcessor:

我给出了这个例子,因为我看到了这个答案:https://stackoverflow.com/a/2349891/4251461

他最初选择BeanFactory用于集成/性能测试,因为他不想加载整个应用程序来测试孤立的bean。然而,他认为BeanFactory不支持类路径XML配置。因此,BeanFactory和ApplicationContext都提供了我想要的关键特性,但两者都没有。

他实现了自己的ApplicationContext,它扩展了ClassPathXmlApplicationContext。

在这里,他可以使用BFPP而不是自定义ApplicationContext。

代码语言:javascript
复制
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容器中配置它:

代码语言:javascript
复制
<bean class="com.example.LazyInitBeanFactoryPostProcessor" />

您还可以在春季看到PropertyPlaceholderConfigurer和PropertyOverrideConfigurer的来源。

2. InitializingBean:

正如索蒂里奥斯·德里马诺奥利所说: InitializingBean接口经常与FactoryBean接口一起使用。它有助于在工厂生成对象之前初始化它。

下面是一个例子。

代码语言:javascript
复制
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:

代码语言:javascript
复制
<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" />

测试它:

代码语言:javascript
复制
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属性实际上(配置为)依赖--注入一个值。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21163355

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档