例子如下:
public class GiraffeService {
//通过的destroy-method属性指定的销毁方法
public void destroyMethod() throws Exception {
System.out.println(“执行配置的destroy-method”);
}
//通过的init-method属性指定的初始化方法
public void initMethod() throws Exception {
System.out.println(“执行配置的init-method”);
}
}
配置文件中的配置:
需要注意的是自定义的init-method
和post-method
方法可以抛异常但是不能有参数。
这种方式比较推荐,因为可以自己创建方法,无需将Bean的实现直接依赖于spring的框架。
3)使用@PostConstruct和@PreDestroy注解
除了xml配置的方式,Spring 也支持用 @PostConstruct
和 @PreDestroy
注解来指定 init
和 destroy
方法。这两个注解均在 javax.annotation
包中。为了注解可以生效,需要在配置文件中定义org.springframework.context.annotation.CommonAnnotationBeanPostProcessor或context:annotation-config
例子如下:
public class GiraffeService {
@PostConstruct
public void initPostConstruct(){
System.out.println(“执行PostConstruct注解标注的方法”);
}
@PreDestroy
public void preDestroy(){
System.out.println(“执行preDestroy注解标注的方法”);
}
}
配置文件:
2.实现*Aware接口 在Bean中使用Spring框架的一些对象
有些时候我们需要在 Bean 的初始化中使用 Spring 框架自身的一些对象来执行一些操作,比如获取ServletContext
的一些参数,获取 ApplicaitionContext
中的 BeanDefinition
的名字,获取 Bean
在容器中的名字等等。为了让 Bean 可以获取到框架自身的一些对象,Spring 提供了一组名为*Aware
的接口。
这些接口均继承于 org.springframework.beans.factory.Aware
标记接口,并提供一个将由 Bean实现的set*方法,Spring通过基于setter的依赖注入方式使相应的对象可以被Bean使用。
网上说,这些接口是利用观察者模式实现的,类似于servlet listeners
,目前还不明白,不过这也不在本文的讨论范围内。
介绍一些重要的Aware接口:
- ApplicationContextAware: 获得
ApplicationContext
对象,可以用来获取所有Bean definition
的名字。 - BeanFactoryAware:获得
BeanFactory
对象,可以用来检测Bean的作用域。 - BeanNameAware:获得Bean在配置文件中定义的名字。
- ResourceLoaderAware:获得
ResourceLoader
对象,可以获得classpath中某个文件。 - ServletContextAware:在一个MVC应用中可以获取
ServletContext
对象,可以读取context中的参数。 - ServletConfigAware: 在一个MVC应用中可以获取
ServletConfig
对象,可以读取config中的参数。
public class GiraffeService implements ApplicationContextAware,
ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware{
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("执行setBeanClassLoader,ClassLoader Name = " +
classLoader.getClass().getName());
}
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println(“执行setBeanFactory,setBeanFactory:: giraffe bean singleton=” + beanFactory.isSingleton(“giraffeService”));
}
@Override
public void setBeanName(String s) {
System.out.println(“执行setBeanName:: Bean Name defined in context=” + s);
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println(“执行setApplicationContext:: Bean Definition Names=”
- Arrays.toString(applicationContext.getBeanDefinitionNames()));
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
System.out.println(“执行setApplicationEventPublisher”);
}
@Override
public void setEnvironment(Environment environment) {
System.out.println(“执行setEnvironment”);
}
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
Resource resource = resourceLoader.getResource(“classpath:spring- beans.xml”);
System.out.println(“执行setResourceLoader:: Resource File Name=” + resource.getFilename());
}
@Override
public void setImportMetadata(AnnotationMetadata annotationMetadata) {
System.out.println(“执行setImportMetadata”);
}
}
3.BeanPostProcessor
上面的*Aware接口是针对某个实现这些接口的Bean定制初始化的过程,
Spring同样可以针对容器中的所有Bean,或者某些Bean定制初始化过程,只需提供一个实现 BeanPostProcessor
接口的类即可。 该接口中包含两个方法,postProcessBeforeInitialization
和 postProcessAfterInitialization
。 postProcessBeforeInitialization
方法会在容器中的Bean初始化之前执行, postProcessAfterInitialization
方法在容器中的Bean初始化之后执行。
例子如下:
public class CustomerBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println(“执行BeanPostProcessor的 postProcessBeforeInitialization方法,beanName=” + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println(“执行BeanPostProcessor的postProcessAfterInitialization 方法,beanName=” + beanName);
return bean;
}
}
要将BeanPostProcessor
的Bean像其他Bean一样定义在配置文件中
4.总结
所以结合第一节控制台输出的内容,Spring Bean的生命周期是这样纸的:
- Bean容器找到配置文件中 Spring Bean 的定义。
- Bean容器利用Java Reflection API创建一个Bean的实例。
- 如果涉及到一些属性值 利用set方法设置一些属性值。
- 如果Bean实现了
BeanNameAware
接口,调用setBeanName()
方法,传入Bean的名字。 - 如果Bean实现了
BeanClassLoaderAware
接口,调用setBeanClassLoader()
方法,传入ClassLoader对象的实例。 - 如果Bean实现了
BeanFactoryAware
接口,调用setBeanFactory()
方法,传入BeanFactory对象的实例。 - 与上面的类似,如果实现了其他
*Aware
接口,就调用相应的方法。 - 如果有和加载这个Bean的Spring容器相关的
BeanPostProcessor
对象,执行
postProcessBeforeInitialization()
方法 - 如果Bean实现了
InitializingBean
接口,执行afterPropertiesSet()
方法。 - 如果Bean在配置文件中的定义包含
init-method
属性,执行指定的方法。 - 如果有和加载这个Bean的Spring容器相关的
BeanPostProcessor
对象,执行postProcessAfterInitialization()
方法 - 当要销毁Bean的时候,如果Bean实现了
DisposableBean
接口,执destroy()
方法。 - 当要销毁Bean的时候,如果Bean在配置文件中的定义包含
destroy-method
属性,执行指定的方法。
与之比较类似的中文版本:
其实很多时候我们并不会真的去实现上面说描述的那些接口,那么下面我们就除去那些接口,针对bean的单例和非单例来描述下bean的生命周期:
5.单例管理的对象
当scope=”singleton”
,即默认情况下,会在启动容器时(即实例化容器时)时实例化。但我们可以指定Bean节点的lazy-init=”true”
来延迟初始化bean,这时候,只有在第一次获取bean时才会初始化bean,即第一次请求该bean时才初始化。如下配置:
如果想对所有的默认单例bean都应用延迟初始化,可以在根节点beans设置default-lazy-init
属性为true,如下所示:
<beans default-lazy-init=“true” …>
默认情况下,Spring 在读取 xml 文件的时候,就会创建对象。在创建对象的时候先调用构造器,然后调用 init-method
属性值中所指定的方法。对象在被销毁的时候,会调用 destroy-method
属性值中所指定的方法(例如调用Container.destroy()
方法的时候)。写一个测试类,代码如下:
public class LifeBean {
private String name;
总结
在清楚了各个大厂的面试重点之后,就能很好的提高你刷题以及面试准备的效率,接下来小编也为大家准备了最新的互联网大厂资料。
![在这里插入图片描述](https://upload-images.jianshu.io/upload_images/24616006-42ba72825e0525b2?imageMogr2/auto-orie 需要zi料+ 绿色徽【vip1024b】
nt/strip%7CimageView2/2/w/1240)
4b】**
nt/strip%7CimageView2/2/w/1240)
[外链图片转存中…(img-4xK4CJu9-1710352885938)]
[外链图片转存中…(img-AHYa55uL-1710352885938)]
[外链图片转存中…(img-QTvdKewK-1710352885939)]