`
cyril0513
  • 浏览: 15679 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

通过Spring提供的接口,改变Spring对Bean的初始化行为

阅读更多
Spring对开闭原则的体现,提供了大量的回调接口,例如BeanPostProcess,该接口的作用是我们可以添加自己的逻辑来控制Bean的初始化构建行为,如我们不想返回Bean本身而是需要返回他的代理对象,修改所依赖的属性对象等等。
下图是BeanPostProcess的关系结构图:
[img]

[/img]
InstantiationAwareBeanPostProcessor 该接口非常重要,在Spring的Aop自动代理的实现中就需要使用该接口,原因很简单,我们的织入我们需要的我们的一些列的逻辑到目标中,所以我们返回的应该目标对象的代理对象。
 public abstract class AbstractAutoProxyCreator extends ProxyConfig
		implements SmartInstantiationAwareBeanPostProcessor, BeanClassLoaderAware, BeanFactoryAware,
		Ordered, AopInfrastructureBean {

.............................................................
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(beanClass, beanName);

		if (!this.targetSourcedBeans.contains(cacheKey)) {
			if (this.advisedBeans.contains(cacheKey) || this.nonAdvisedBeans.contains(cacheKey)) {
				return null;
			}
			if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
				this.nonAdvisedBeans.add(cacheKey);
				return null;
			}
		}

		// Create proxy here if we have a custom TargetSource.
		// Suppresses unnecessary default instantiation of the target bean:
		// The TargetSource will handle target instances in a custom fashion.
                //获取目标源
		TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
		if (targetSource != null) {
			this.targetSourcedBeans.add(beanName);
			Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
                        //重点看这句,创建代理对象,通过ProxyFactory(aop的代码编程方式)
			Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
			this.proxyTypes.put(cacheKey, proxy.getClass());
                        //然后返回代理对象
			return proxy;
		}

		return null;
	}



}





以InstantiationAwareBeanPostProcessor为例(其他的都一样类似)
public class InstantiationAwareBeanPostProcessorImp implements
		InstantiationAwareBeanPostProcessor {

	@Override
	public Object postProcessBeforeInitialization(Object bean, String beanName)
			throws BeansException {
		System.out.println("postProcessBeforeInitialization" + bean
				+ " beanName:" + beanName);

		return bean;
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName)
			throws BeansException {
		// TODO Auto-generated method stub
		return bean;
	}

	/**
	 *
	 */
	@Override
	public Object postProcessBeforeInstantiation(Class<?> beanClass,
			String beanName) throws BeansException {

		System.out.println("postProcessBeforeInstantiation(class)" + beanClass
				+ " beanName:" + beanName);
		
		//此处修改了Bean本身所需要的实例对象,阻断了Spring的创建Bean执行流                              程

		return new InstantiationAwareBeanPostProcessorImp();
	}

	@Override
	public boolean postProcessAfterInstantiation(Object bean, String beanName)
			throws BeansException {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public PropertyValues postProcessPropertyValues(PropertyValues pvs,
			PropertyDescriptor[] pds, Object bean, String beanName)
			throws BeansException {
		System.out.println("postProcessPropertyValues");
		return null;
	}

}



当Spring在执行创建Bean的时候,会先去执行InstantiationAwareBeanPostProcessor 该接口里面的postProcessBeforeInstantiation如果返回的不是null则调用BeanPostProcessor.postProcessAfterInitialization方法,如上例我们修改了bean本省应该返回的实例,只要这2个方法不返回NULL,Spring就会停止后面的Bean的创建,直接返回该实例(return new InstantiationAwareBeanPostProcessorImp())

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

		if (logger.isDebugEnabled()) {
			logger.debug("Creating instance of bean '" + beanName + "'");
		}
		// Make sure bean class is actually resolved at this point.
		resolveBeanClass(mbd, beanName);

		// Prepare method overrides.
		try {
			mbd.prepareMethodOverrides();
		}
		catch (BeanDefinitionValidationException ex) {
			throw new BeanDefinitionStoreException(mbd.getResourceDescription(),
					beanName, "Validation of method overrides failed", ex);
		}

		try {
			// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
                       //在这里执行InstantiationAwareBeanPostProcessor里面的方法,
                      // 如果返回值不为NULL直接退出
			Object bean = resolveBeforeInstantiation(beanName, mbd);
			if (bean != null) {
				return bean;
			}
		}
		catch (Throwable ex) {
			throw new BeanCreationException(mbd.getResourceDescription(), beanName,
					"BeanPostProcessor before instantiation of bean failed", ex);
		}
                //否则去执行后续的创建过程
		Object beanInstance = doCreateBean(beanName, mbd, args);
		if (logger.isDebugEnabled()) {
			logger.debug("Finished creating instance of bean '" + beanName + "'");
		}
		return beanInstance;
	}


  • 大小: 30.6 KB
分享到:
评论

相关推荐

    详解Spring 中如何控制2个bean中的初始化顺序

    例如,可以使用 Spring 的 @Order 注解来指定 bean 的初始化顺序,也可以使用 Spring 的生命周期接口(如 InitializingBean)来控制 bean 的初始化顺序。 总结 控制 2 个 bean 的初始化顺序是一个常见的问题,本篇...

    Spring Bean创建初始化流程.docx

    9. **Bean初始化**: 最后,`initializeBean(beanName, exposedObject, mbd)`对创建好的Bean进行初始化,包括调用初始化方法(如果有`@PostConstruct`注解的方法),以及执行AOP代理等操作。 整个流程中,Spring...

    Spring bean初始化及销毁你必须要掌握的回调方法.docx

    下面将详细介绍如何通过不同方式定义Spring Bean的初始化和销毁回调方法。 **初始化回调方法** 1. **@PostConstruct注解** 这个Java标准注解用于标记一个方法,该方法将在对象完全构造后但在业务逻辑执行前被调用...

    Spring Bean的初始化和销毁实例详解

    Spring Bean的初始化和销毁实例详解 Spring Bean的初始化和销毁是Spring框架中一个非常重要的概念,它们都是Bean生命周期中不可或缺的一部分。在Spring框架中,我们可以使用多种方式来控制Bean的初始化和销毁,以下...

    Spring源码学习六:bean初始化1

    在本篇文章中,我们将深入探讨Spring源码中关于Bean初始化的过程,特别是`finishBeanFactoryInitialization()`方法和`preInstantiateSingletons()`方法。 首先,`finishBeanFactoryInitialization(Confi‌...

    Spring实例化Bean顺序

    但是,这并不总是可靠的,因为Spring通常会延迟初始化Bean,除非显式要求或存在依赖关系。 2. **依赖注入**:Spring容器会根据Bean之间的依赖关系来决定实例化顺序。如果一个Bean依赖于另一个Bean,那么被依赖的...

    spring容器初始化bean和销毁bean之前进行一些操作的方法

    此外,Spring提供了BeanPostProcessor接口,允许我们在Bean初始化前后进行自定义处理。通过实现`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`方法,可以在Bean实例化和初始化之后进行...

    Spring中与Bean相关的接口

    它提供两个方法:`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`,分别在Bean初始化之前和之后调用,可以用来进行额外的处理或校验。 在Bean的定义中,我们可以使用`@Component`、`@...

    初始化后可访问Spring管理的Bean

    初始化后可访问Spring管理的Bean

    浅谈spring容器中bean的初始化

    5. **Bean的生命周期管理**:Spring提供了预初始化、初始化、后初始化等一系列回调接口(如`InitializingBean`和自定义的初始化方法),使得开发者可以在Bean的生命周期中插入自定义逻辑。 总的来说,Spring容器对...

    spring bean XML配置入门

    一旦XML配置加载到Spring容器中,容器将根据配置创建Bean实例,并按照定义进行初始化、依赖注入,最后完成Bean的生命周期管理。 10. **实践操作**: 在实际开发中,我们可以使用Eclipse的Spring插件来简化Bean...

    springBean加载过程源码解析文档,附有代码类名和行数

    Spring Bean 加载过程是 Spring 框架中最核心的部分之一,涉及到 ApplicationContext 的初始化、Bean 的加载和注册等过程。在 Spring Boot 应用程序中,SpringApplication 负责加载和管理 Bean。 SpringApplication...

    spring bean的生命周期

    - **XML配置**:在传统的Spring应用中,Bean的定义通常写在XML配置文件中,如`springbean-xml`中的配置。 - **注解配置**:使用`@Component`,`@Service`,`@Repository`和`@Controller`注解标记类,配合`@...

    spring bean life cycle

    通过实现`postProcessBeforeInitialization()`和`postProcessAfterInitialization()`方法,可以在Bean初始化前后进行额外的操作。 在Spring容器中,Bean的生命周期管理也支持通过`BeanDefinition`进行定制。例如,...

    Spring bean 动态注册,jar包热替换

    Spring bean 一般通过配置文件和注解进行加载,如果要实现jar或class...测试示例中是spring boot 的部分代码,动态加载的内容为接口实现类,且初始化时加载本地的实现类,动态加载后改为非程序加载目录中的jar实现类。

    Spring 源码分析(Bean的初始化)

    总结起来,Spring的Bean初始化是一个复杂而精细的过程,涉及XML解析、BeanDefinition的构建、依赖注入、初始化回调、AOP代理等多个环节。通过深入理解这一过程,开发者能更好地掌握Spring框架的工作原理,从而更高效...

    Spring Bean重复执行两次(实例被构造两次)问题分析

    3. **@PostConstruct与初始化回调**:Spring允许我们在Bean初始化后执行特定代码,通常通过`@PostConstruct`注解的方法来实现。如果这个方法被意外地调用了两次,那么Bean也会被构造两次。检查是否有多处调用或配置...

    Spring Bean 加载顺序 .

    7. **Bean初始化**: 实例化完成后,Spring会执行Bean的初始化方法,包括调用`@PostConstruct`注解的方法。同时,如果Bean实现了InitializingBean接口,其`afterPropertiesSet()`方法也会被调用。 8. **初始化后...

    Spring Bean生命周期.pdf

    - InitializingBean:对应初始化阶段,它提供了afterPropertiesSet方法供开发者实现Bean初始化逻辑。 - DisposableBean:对应销毁阶段,它提供了destroy方法供开发者实现Bean销毁逻辑。 整个Spring Bean的生命...

Global site tag (gtag.js) - Google Analytics