对于prototype作用域的bean。Spring容器仅仅负责创建Bean的实例。Bean完全由客服端的代码管理,容器不再去跟踪他们的生命周期。每次都去创建新的实例,无法管理哦。好多的个数。
对于单例Bean,每次都会返回一个共享的实例,客服端不能控制Bean的销毁,spring容器负责跟踪Bean实例的产生,销毁。spring容器可以在创建Bean之后,进行某些资源的申请;还可以在销毁Bean之前,对于某些资源的回收,比如数据库的连接
销毁之前(即将销毁bean之前)
Spring 容器可以控制 bean 的生命周期,通过实SpringInitializingBean 和DisposableBean 接口。容器会调用 InitializingBean 接口的afterPropertiesSet()方法,也会调用 DisposableBean 接口的 destroy()方法。 ,也就是运行 bean 自定义的初始化方法和销毁方法
Tip:在现代 Spring 应用中,一般都是用@PostConstruct 和@PreDestroy 注解定义生命周期回调函数。使用注解的话,你的 bean 就无需和Spring API 耦合了。
If you don’t want to use the JSR-250 annotations but you are still looking to remove coupling consider the use of init-method and destroy-method object definition metadata. 如果不想使用注解,可以使用元数据标签的
Spring 使用 BeanPostProcessor 实现类处理所有的回调接口并调用相应的方法,接口由 Spring 负责查找。若需要自定义功能或其他生命周期行为, Spring 并未提供开箱即用的支持,但是可以自己实现BeanPostProcessor 类。
package org.springframework.beans.factory.config;
import org.springframework.beans.BeansException;
/** * @author Juergen Hoeller * @since 10.10.2003 * @see InstantiationAwareBeanPostProcessor * @see DestructionAwareBeanPostProcessor * @see ConfigurableBeanFactory#addBeanPostProcessor * @see BeanFactoryPostProcessor */
public interface BeanPostProcessor
/** * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet */
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
/** * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet * @see org.springframework.beans.factory.FactoryBean */
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}
除了上面的,还可以使用lifecycle处理这些问题: Spring-managed objects may also implement the Lifecycle interface so that those objects can participate in the startup and shutdown process as driven by the container’s own lifecycle.
package org.springframework.context;
/** * * @see ConfigurableApplicationContext * @see org.springframework.jms.listener.AbstractMessageListenerContainer * @see org.springframework.scheduling.quartz.SchedulerFactoryBean */
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
public interface LifecycleProcessor extends Lifecycle {
/** * Notification of context refresh, e.g. for auto-starting components. */
void onRefresh();
/** * Notification of context close phase, e.g. for auto-stopping components. */
void onClose();
}
初始化回调
package org.springframework.beans.factory;
/** * @author Rod Johnson * @see BeanNameAware * @see BeanFactoryAware * @see BeanFactory * @see org.springframework.beans.factory.support.RootBeanDefinition#getInitMethodName * @see org.springframework.context.ApplicationContextAware */
public interface InitializingBean {
/** * 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. */
void afterPropertiesSet() throws Exception;
}
推荐,尽量不用 InitializingBean 接口,因为这将导致不必要的与 Spring 的耦合。还有更好的办法,使用@PostConstruct 注解,或者指定一个 POJO 的initialization 方法。 XML 配置元数据中,使用 init-method 属性用来指定,其值为初始化方法名
例如:
init-method在全部设置执行完之后执行。
<bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
public class ExampleBean {
public void init() {
// do some initialization work
}
}
下面这个是和spring没有解耦的
<bean id="exampleInitBean" class="examples.AnotherExampleBean"/>
public class AnotherExampleBean implements InitializingBean {
public void afterPropertiesSet() {
// do some initialization work
}
}
org.springframework.beans.factory.DisposableBean,@PreDestroy,destroy-method。这些都是差不多的啊!和上面的类似的作用。我们不太需要了解好多!
public class AnotherExampleBean implements DisposableBean {
public void destroy() {
// do some destruction work (like releasing pooled connections)
}
}
默认的初始化函数和销毁函数,不需要通过init-method之类的东西!不需要配置,只要命名规范就行了!
有三种生命周期回调机制,或者说是三种方式实现:InitializingBean 和 DisposableBean 回调接口;自定义 init()
和 destroy()方法; @PostConstruct and @PreDestroy 注解。这些方式可以混合使用
在一个非 web 应用的环境中使用 Spring IoC 容器;比如,在一个富客户端桌面环境中;得在 JVM 中注册一个 shutdown 钩子。这么做是为了安全的关闭,关闭时保证所单例 bean 的相关的 destroy 方法会被调用,这样就可以释放所的资源。当然了,你必须得正确的配置和实现销毁回调。要注册 shutdown 钩子,得调用 registerShutdownHood()方法,该方法在
AbstractApplicationContext 类中
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public final class Boot {
public static void main(final String[] args) throws Exception {
AbstractApplicationContext ctx = new ClassPathXmlApplicationContext(
new String []{"beans.xml"});
// add a shutdown hook for the above context...
ctx.registerShutdownHook();
// app runs here...
// main method exits, hook is called prior to the app shutting down...
}
}
因此可以编程式的使用 ApplicationContext 手动的创建 bean,通过ApplicationContext 接口或者是该接口的子类,比如ConfigurableApplicationContext,该类还增加了方法。用途之一是编程式的检索 bean,有时非常有用。然而,大多数情况下,要避免编程式检索 bean,这样的话你的代码就会和 Spring 耦合,这不是 IoC 的风格, Ioc 的风格是协作类作为 bean 的属性。 ApplicationContext 类的其他方法提供了文件资源的访问接口、发布应用事件、访问 MessageSource 消息资源
org.springframework.beans.factory.BeanNameAware 接口的实现类,若是由ApplicationContext 创建了该类的实例,该实例将会持有相关的对象定义的引用
还有好多的Aware
除了ApplicationContextAware和BeanNameAware上面所讨论的,Spring提供了 范围的Aware接口允许bean来表示他们的容器 需要一定的基础设施依赖。 最重要的Aware接口 总结如下
Spring bean 定义包含各种配置信息,包括构造参数,属性值,容器特定信息例如初始化方法、静态工厂方法等等。 Spring 子 bean 定义继承父bean 定义配置。子 bean 能覆盖值,若有需要还能增加其他配置。使用继承能少打好多字。这是模板的一种形式,讲究的就是效率
若子 bean 中未指定 class 属性,则子 bean 集成父 bean 的 class 属性,子bean 可以重写覆盖此属性。若要覆盖重写 class 属性,子 bean 的 class 类型必须兼容父 bean 的 class,也就是,子 bean 必须能接收父 bean 的属性值。其他的属性也是通常取自子 bean 的配置: depends on, autowire mode,dependency check, singleton, lazy init.
<bean id="inheritedTestBean" abstract="true" class="org.springframework.beans.TestBean">
<property name="name" value="parent"/>
<property name="age" value="1"/>
</bean>
<bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean" parent="inheritedTestBean" init-method="initialize">
<property name="name" value="override"/>
<!-- the age property value of 1 will be inherited from parent -->
</bean>
其实很简单的,就和是一个复用的问题。