栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring 注解驱动开发

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring 注解驱动开发

本节主要来探讨一下 BeanPostProcessor 的执行流程。

一、基础环境

实体类 Car

package org.example.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

public class Car implements InitializingBean, DisposableBean {

 	private String brand;
    private String price;

    public String getBrand() {
        return brand;
    }

    public void setBrand(String brand) {
        this.brand = brand;
    }

    public String getPrice() {
        return price;
    }

    public Car(){
        System.out.println("car constructor...");
    }

    public void initCar(){
        System.out.println("car ... initCar...");
    }

    public void destoryCar(){
        System.out.println("car ... destoryCar");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("car......DisposableBean......destory");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("car......InitializingBean......afterPropertiesSet");
    }

    @PostConstruct
    public void initPostConstruct(){
        System.out.println("car......initPostConstruct......");
    }

    @PreDestroy
    public void initPreDestroy(){
        System.out.println("car......initPreDestroy......");
    }
}

创建 MyBeanPostProcessor 类,用于实现 BeanPostProcessor 接口

package org.example.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..." + beanName + "--->" + bean);
        return bean;
    }

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

	@Override
    public String toString() {
        return "Car{" +
                "brand='" + brand + ''' +
                ", price='" + price + ''' +
                '}';
    }
}

配置类:

package org.example.config;

import org.example.pojo.Car;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
@ComponentScan("org.example.processor")
public class InitAndDestoryTestConfig {

    @Bean(initMethod = "initCar", destroyMethod = "destoryCar")
    public Car car(){
        Car car = new Car();
        car.setBrand("奥迪");
        car.setPrice("70万");
        return car;
    }
}

测试方法:

package org.example.test;

import org.example.config.*;
import org.example.pojo.Person;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.Environment;

import java.sql.SQLOutput;
import java.util.Map;

public class AnnotationMainTest {
    @Test
    public void testInitAndDestory(){
        AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(InitAndDestoryTestConfig.class);
        System.out.println("容器创建完成......");
        Object car = ac.getBean("car");
        Object car1 = ac.getBean("car");
        System.out.println(car);
        System.out.println(car1);
        System.out.println(car == car1);
        ac.close();
    }
}

二、原理 2.1 执行流程

首先在 MyBeanPostProcessor 的两个方法上打上断点

以 DEBUG 形式运行测试方法,先来看一下方法调用栈:

先根据方法调用栈梳理一下大致的流程:

2.2 doCreateBean 方法

重点看一下AbstractAutowireCapableBeanFactory 类中 doCreateBean 方法

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
			throws BeanCreationException {

		// Instantiate the bean.
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
			// 该方法用于创建 bean 实例
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = instanceWrapper.getWrappedInstance();
		Class beanType = instanceWrapper.getWrappedClass();
		if (beanType != NullBean.class) {
			mbd.resolvedTargetType = beanType;
		}

		// Allow post-processors to modify the merged bean definition.
		synchronized (mbd.postProcessingLock) {
			if (!mbd.postProcessed) {
				try {
					applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
				}
				catch (Throwable ex) {
					throw new BeanCreationException(mbd.getResourceDescription(), beanName,
							"Post-processing of merged bean definition failed", ex);
				}
				mbd.postProcessed = true;
			}
		}

		// Eagerly cache singletons to be able to resolve circular references
		// even when triggered by lifecycle interfaces like BeanFactoryAware.
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
			if (logger.isTraceEnabled()) {
				logger.trace("Eagerly caching bean '" + beanName +
						"' to allow for resolving potential circular references");
			}
			addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));
		}

		// Initialize the bean instance.
		Object exposedObject = bean;
		try {
			// populateBean 方法完成了 bean 的属性注入
			populateBean(beanName, mbd, instanceWrapper);
			// 初始化 bean
			exposedObject = initializeBean(beanName, exposedObject, mbd);
		}
		catch (Throwable ex) {
			if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
				throw (BeanCreationException) ex;
			}
			else {
				throw new BeanCreationException(
						mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
			}
		}

		if (earlySingletonExposure) {
			Object earlySingletonReference = getSingleton(beanName, false);
			if (earlySingletonReference != null) {
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
					String[] dependentBeans = getDependentBeans(beanName);
					Set actualDependentBeans = new linkedHashSet<>(dependentBeans.length);
					for (String dependentBean : dependentBeans) {
						if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
							actualDependentBeans.add(dependentBean);
						}
					}
					if (!actualDependentBeans.isEmpty()) {
						throw new BeanCurrentlyInCreationException(beanName,
								"Bean with name '" + beanName + "' has been injected into other beans [" +
								StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
								"] in its raw version as part of a circular reference, but has eventually been " +
								"wrapped. This means that said other beans do not use the final version of the " +
								"bean. This is often the result of over-eager type matching - consider using " +
								"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");
					}
				}
			}
		}

		// Register bean as disposable.
		try {
			registerDisposableBeanIfNecessary(beanName, bean, mbd);
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanCreationException(
					mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);
		}

		return exposedObject;
	}

该方法主要做了以下几件事:

通过 createBeanInstance 方法完成 bean 实例的创建调用 populateBean 方法完成 bean 的属性注入调用 initializeBean 方法完成 bean 的初始化调用 registerDisposableBeanIfNecessary 方法,将一些需要在容器关闭时执行销毁方法的 bean 的添加到 bean 列表中 2.3 initializeBean 方法

重点看下 initializeBean 方法

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction) () -> {
				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;
	}
 

initializeBean 方法主要做了以下几件事:

调用 invokeAwareMethods,根据传入的参数 bean 实例,判断该 bean 实例实现了哪种 Aware 接口,并执行对应的方法。调用 applyBeanPostProcessorsBeforeInitialization,执行后置处理器的初始化前方法。调用 invokeInitMethods,执行初始化方法。调用 applyBeanPostProcessorsAfterInitialization,执行后置处理器的初始化后方法。 2.4.1 invokeAwareMethods 方法

private void invokeAwareMethods(final String beanName, final Object bean) {
	if (bean instanceof Aware) {
		if (bean instanceof BeanNameAware) {
			((BeanNameAware) bean).setBeanName(beanName);
		}
		if (bean instanceof BeanClassLoaderAware) {
			ClassLoader bcl = getBeanClassLoader();
			if (bcl != null) {
				((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
			}
		}
		if (bean instanceof BeanFactoryAware) {
			((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
		}
	}
}
2.4.2 applyBeanPostProcessorsBeforeInitialization 方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
	throws BeansException {

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

applyBeanPostProcessorsBeforeInitialization 方法获取到当前 bean 的所有的后置处理器,并循环遍历执行后置处理器的 postProcessBeforeInitialization 方法,并将执行结果返回。

2.4.3 invokeInitMethods 方法:
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
			throws Throwable {

		boolean isInitializingBean = (bean instanceof InitializingBean);
		if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
			if (logger.isTraceEnabled()) {
				logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
			}
			if (System.getSecurityManager() != null) {
				try {
					AccessController.doPrivileged((PrivilegedExceptionAction) () -> {
						((InitializingBean) bean).afterPropertiesSet();
						return null;
					}, getAccessControlContext());
				}
				catch (PrivilegedActionException pae) {
					throw pae.getException();
				}
			}
			else {
				((InitializingBean) bean).afterPropertiesSet();
			}
		}

		if (mbd != null && bean.getClass() != NullBean.class) {
			String initMethodName = mbd.getInitMethodName();
			if (StringUtils.hasLength(initMethodName) &&
					!(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
					!mbd.isExternallyManagedInitMethod(initMethodName)) {
				invokeCustomInitMethod(beanName, bean, mbd);
			}
		}
	}

 

invokeInitMethods 方法主要做了以下两件事:

如果当前 bean 实现了 InitializingBean 接口中的 afterPropertiesSet 方法,执行 afterPropertiesSet 方法如果当前 bean 中指定了 initMethod(通过 @Bean 注解中 initMethod 属性或者Spring的 XML 配置文件中 bean 标签中的 init-method 属性),通过反射执行 initMethod 方法 2.4.4 applyBeanPostProcessorsAfterInitialization 方法

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

	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		Object current = processor.postProcessAfterInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

取出当前 bean 的所有后置处理器,循环遍历执行后置处理器的 postProcessAfterInitialization 方法

三、BeanPostProcessor 在 Spring 底层中的使用

接口 BeanPostProcessor 有很多的实现类,以下截图也只展示了其中的一部分:

其中,我们以 ApplicationContextAwareProcessor 为例,具体介绍下 BeanPostProcessor 接口在 Spring 中的应用。

先来看一下源码:

class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}


	@Override
	@Nullable
	public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
		if (!(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
				bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
				bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)){
			return bean;
		}

		AccessControlContext acc = null;

		if (System.getSecurityManager() != null) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged((PrivilegedAction) () -> {
				invokeAwareInterfaces(bean);
				return null;
			}, acc);
		}
		else {
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		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);
		}
	}

}

 

ApplicationContextAwareProcessor 是 BeanPostProcessor 接口的实现类,所以也就实现了 postProcessBeforeInitialization 方法。在 postProcessBeforeInitialization 方法中,ApplicationContextAwareProcessor 主要做了两件事:

根据传入 bean 实例,判断当前 bean 实例是否实现了以下几个接口:
EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware,如果没有实现,则直接返回当前 bean 实例如果实现了上述接口中的某一个,则调用 invokeAwareInterfaces 方法

这里说一下 Aware 接口:

public interface Aware {

}

Aware 接口实际上是一个标记接口(又称标签接口,指不包含任何方法的接口),具体的方法需要由各个子接口去确定,但通常该方法是一个仅接收单个参数的无返回值(void)的方法。实现 Aware 接口的 bean 在被初始化之后,可以通过这个无返回值的方法取得一些对应的资源。这也就表明不同的 Aware 子接口获取到的资源其实是不一样的。通过 ApplicationContextAwareProcessor 中的 invokeAwareInterfaces 方法便可以看出,如果当前 bean 实现了 EnvironmentAware 接口,则可以获取到当前容器运行的环境信息,如果当前 bean 实现了 ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware 或者 ApplicationContextAware,则可以获取到当前容器的信息。

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号