Spring注解驱动开发——生命周期

一、@Bean指定初始化和销毁方法

Bean的生命周期指的是创建、初始化、销毁的过程。容器管理bean的生命周期,我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

创建Boy类,自定义初始化和销毁方法

public class Boy extends Man {

    public Boy(){
        System.out.println("执行Boy构造方法......");
    }

    public void init(){
        System.out.println("执行Boy初始化方法......");
    }

    public void destroy(){
        System.out.println("执行Boy销毁方法......");
    }
}

在配置类中,将Boy类注册到IOC容器中,并指定自定义的Boy的初始化和销毁方法

@Configuration
public class MainConfigOfLifeCycle {

    @Bean(initMethod = "init",destroyMethod = "destroy")
    public Boy boy(){
        return new Boy();
    }

}

测试

    @Test
    public void testLifeCycle(){
        //创建ioc容器
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("IOC容器创建完成......");

        //关闭容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = (AnnotationConfigApplicationContext) context;
        annotationConfigApplicationContext.close();
    }

输出结果:
在这里插入图片描述

  • 构造方法:单实例在容器启动的时候调用构造方法,创建对象;多实例在每次获取对象的时候才会调用构造方法创建对象。
  • 初始化:对象创建完成,并且赋值后,会调用初始化方法。
  • 销毁:单实例在容器关闭的时候调用销毁方法;而多实例,容器不会去管理这个bean,也就不会调用销毁方法,需要手动调用销毁方法。

二、InitializingBean接口和DisposableBean接口

通过让Bean实现InitializingBean接口来定义初始化伙计,实现DisposableBean接口来定义销毁逻辑

public interface InitializingBean {
    void afterPropertiesSet() throws Exception;
}
public interface DisposableBean {
    void destroy() throws Exception;
}
public class Girl implements InitializingBean, DisposableBean {

    public Girl(){
        System.out.println("执行Girl构造方法......");
    }

    public void destroy() throws Exception {
        System.out.println("执行Girl销毁方法......");
    }

    public void afterPropertiesSet() throws Exception {
        System.out.println("执行Girl初始化方法......");
    }
}

在配置类中将Girl注册到容器中

    @Bean
    public Girl girl(){
        return new Girl();
    }

测试

    @Test
    public void testLifeCycle(){
        //创建ioc容器
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("IOC容器创建完成......");

        //关闭容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = (AnnotationConfigApplicationContext) context;
        annotationConfigApplicationContext.close();
    }

输出结果:
在这里插入图片描述

三、@PostConstruct@PreDestroy注解

@PostConstruct注解可以在bean创建完成并且属性赋值完成,来执行初始化方法

@PreDestroy注解可以在容器销毁bean之前进行一些清理工作

public class Woman {

    public Woman(){
        System.out.println("执行Woman构造器方法......");
    }

    @PostConstruct
    public void init(){
        System.out.println("执行Woman的PostConstruct方法......");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("执行Woman的PreDestroy方法......");
    }
}

输出结果:
在这里插入图片描述

四、BeanPostProcessor后置处理器

BeanPostProcessor是一个接口,它是bean的后置处理器,在bean初始化前后进行一些处理工作

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object var1, String var2) throws BeansException;

    Object postProcessAfterInitialization(Object var1, String var2) throws BeansException;
}

创建自定义的后置处理器,实现BeanPostProcessor接口中的两个方法

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {

    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization ==> " + beanName + " == >" + bean);
        return bean;
    }

    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization ==> " + beanName + " == >" + bean);
        return bean;
    }
}

输出结果:
在这里插入图片描述

后置处理器的原理:

	/**
	 * Initialize the given bean instance, applying factory callbacks
	 * as well as init methods and bean post processors.
	 * <p>Called from {@link #createBean} for traditionally defined beans,
	 * and from {@link #initializeBean} for existing bean instances.
	 * @param beanName the bean name in the factory (for debugging purposes)
	 * @param bean the new bean instance we may need to initialize
	 * @param mbd the bean definition that the bean was created with
	 * (can also be {@code null}, if given an existing bean instance)
	 * @return the initialized bean instance (potentially wrapped)
	 * @see BeanNameAware
	 * @see BeanClassLoaderAware
	 * @see BeanFactoryAware
	 * @see #applyBeanPostProcessorsBeforeInitialization
	 * @see #invokeInitMethods
	 * @see #applyBeanPostProcessorsAfterInitialization
	 */
	protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareMethods(beanName, bean);
					return null;
				}
			}, getAccessControlContext());
		}
		else {
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}

		if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
		return wrappedBean;
	}

在执行初始化之前,首先调用applyBeanPostProcessorsBeforeInitialization方法,遍历得到容器中BeanPostProcessor,挨个执行postProcessBeforeInitialization方法,一旦返回null就跳出for循环,不会再执行后面的后置处理器postProcessBeforeInitialization方法。这样就实现了所有的bean进行初始化之前的处理。

	@Override
	public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
			throws BeansException {

		Object result = existingBean;
		for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) {
			result = beanProcessor.postProcessBeforeInitialization(result, beanName);
			if (result == null) {
				return result;
			}
		}
		return result;
	}

然后调用invokeAwareMethods方法执行所有的初始化方法。

在执行完初始化之后,调用applyBeanPostProcessorsAfterInitialization方法,同applyBeanPostProcessorsBeforeInitialization方法一样,遍历所有的后置处理器执行postProcessAfterInitialization方法,实现对所有的bean进行初始化之后的处理。

doCreateBean方法中,执行初始化之前首先调用了populateBean方法完成对属性的赋值以后,才会挨个执行上述的后置处理器的方法。

		try {
			populateBean(beanName, mbd, instanceWrapper);
			if (exposedObject != null) {
				exposedObject = initializeBean(beanName, exposedObject, mbd);
			}
		}

后置处理器在Spring底层的使用:

ApplicationContextAwareProcessor后置处理器

ApplicationContextAwareProcessorBeanPostProcessor接口的一个实现类,它可以在组件里面注入IOC容器。

实现ApplicationContextAware接口,调用setApplicationContext方法给Woman组件注入IOC容器

public class Woman implements ApplicationContextAware{
    
    private ApplicationContext applicationContext;

    public Woman(){
        System.out.println("执行Woman构造器方法......");
    }

    @PostConstruct
    public void init(){
        System.out.println("执行Woman的PostConstruct方法......");
    }

    @PreDestroy
    public void destroy(){
        System.out.println("执行Woman的PreDestroy方法......");
    }


    //注入IOC容器
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

IOC容器的注入,就是ApplicationContextAwareProcessor这个后置处理器实现的。在创建Woman对象还没有初始化之前调用postProcessBeforeInitialization方法,判断Woman对象是否实现了ApplicationContextAware接口,如果实现了就会调用invokeAwareInterfaces方法注入值。

	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

invokeAwareInterfaces方法判断bean的类型,即实现了哪一个接口,然后进行强制类型转换ApplicationContextAware,调用setApplicationContext方法把IOC容器注入过去。Woman对象也就可以获取到IOC容器了。

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

debug调试可以看出,在执行womansetApplicationContext方法之前,调用执行了ApplicationContextAwareProcessor这个后置处理器,实现了IOC容器的注入。
在这里插入图片描述

BeanValidationPostProcessor数据校验后置处理器

会在初始化之前和之后进行数据校验

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!this.afterInitialization) {
			doValidate(bean);
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (this.afterInitialization) {
			doValidate(bean);
		}
		return bean;
	}

InitDestroyAnnotationBeanPostProcessor后置处理器

用来处理@PostConstruct@PreDestroy注解

	/**
	 * Specify the init annotation to check for, indicating initialization
	 * methods to call after configuration of a bean.
	 * <p>Any custom annotation can be used, since there are no required
	 * annotation attributes. There is no default, although a typical choice
	 * is the JSR-250 {@link javax.annotation.PostConstruct} annotation.
	 */
	public void setInitAnnotationType(Class<? extends Annotation> initAnnotationType) {
		this.initAnnotationType = initAnnotationType;
	}

	/**
	 * Specify the destroy annotation to check for, indicating destruction
	 * methods to call when the context is shutting down.
	 * <p>Any custom annotation can be used, since there are no required
	 * annotation attributes. There is no default, although a typical choice
	 * is the JSR-250 {@link javax.annotation.PreDestroy} annotation.
	 */
	public void setDestroyAnnotationType(Class<? extends Annotation> destroyAnnotationType) {
		this.destroyAnnotationType = destroyAnnotationType;
	}

@PostConstruct注解对应postProcessBeforeInitialization方法

@PreDestroy注解对应postProcessBeforeDestruction方法

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeInitMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			throw new BeanCreationException(beanName, "Invocation of init method failed", ex.getTargetException());
		}
		catch (Throwable ex) {
			throw new BeanCreationException(beanName, "Failed to invoke init method", ex);
		}
		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		return bean;
	}

	@Override
	public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
		LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
		try {
			metadata.invokeDestroyMethods(bean, beanName);
		}
		catch (InvocationTargetException ex) {
			String msg = "Invocation of destroy method failed on bean with name '" + beanName + "'";
			if (logger.isDebugEnabled()) {
				logger.warn(msg, ex.getTargetException());
			}
			else {
				logger.warn(msg + ": " + ex.getTargetException());
			}
		}
		catch (Throwable ex) {
			logger.error("Failed to invoke destroy method on bean with name '" + beanName + "'", ex);
		}
	}

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值