文档章节

SprintBoot中如何构造Bean&原理分析

强子1985
 强子1985
发布于 2017/05/21 09:49
字数 747
阅读 41
收藏 0

MySpringBoot打算构造加入Bean的功能,代码完成,下面解释操作&原理。

-----------------------------------------------------------------------------

获取Bean有2种方法,

1)拿到Web容器里的ApplicationContext,调用getBean(Class)方法

2)直接在类里使用Autowired注解

-----------------------------------------------------------------------------

下面就来解释这2点

1)拿到ApplicationContext,代码调用getBean

写上1个类

package helper;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import controller.UserExample;

//使用方法
//在任何类中调用
//YourClass aaa=(YourClass) BeanContextHelper.getApplicationContext().getBean(YourClass.class);

@Component
public class BeanContextHelper implements ApplicationContextAware {

	private static ApplicationContext applicationContext = null;

	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		if (null == applicationContext) {
			applicationContext = context;
		}
		System.out.println("setApplicationContext invoked...");
	}

	public static ApplicationContext getApplicationContext() {
		return applicationContext;
	}
}

这个类所在的package必须在boot main类的scan路径内。

然后setApplicationContext的方法会被调用,我们看一下调用栈

at helper.BeanContextHelper.setApplicationContext(BeanContextHelper.java:21)
	at org.springframework.context.support.ApplicationContextAwareProcessor.invokeAwareInterfaces(ApplicationContextAwareProcessor.java:121)
	at org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:97)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:409)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1620)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151)
	at server.Boot.main(Boot.java:13)

为什么会触发到这个函数呢?

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);
			}
		}
	}

其实也就是,对于单例的bean,web启动时,预先构造,然后做一些初始化操作。

因为上面这个类implements ApplicationContextAware接口,所以会执行最后1行代码。

所以,如果你在任何类里面写上

FirstBean bean = (FirstBean) BeanContextHelper.getApplicationContext().getBean(FirstBean.class);
System.out.println(bean);

就会拿到这个Bean的单例对象。

 

2)通过@Autowired注解

这个是自动装配,让我们看如何实现的。

假设我们有这么1个Controller类,代码如下:

package controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import bean.FirstBean;

@RestController
@RequestMapping("/user")
public class UserExample {
	
	public UserExample() {
		System.out.println("user example . bean --->"+bean);
		new Exception().printStackTrace();
	}

	@SuppressWarnings("unused")
	@Autowired
	private FirstBean bean;

	@RequestMapping(value = "/hi", method = { RequestMethod.GET })
	public String index() {
		return "{\"hello\":\"world\"}";
	}
}

我们看到有1个Autowired注解,什么时候发挥作用的呢?

想找到这个很简单,注入一个prototype的类,打印这个prototype的栈就可以了。

尝试一把,确实可以,注入属性的位置是

at bean.ProtoTypeBean.<init>(ProtoTypeBean.java:10)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
	at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
	at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
	at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
	at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:142)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:89)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:325)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:202)
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1138)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:366)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1264)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:553)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:866)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:542)
	at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:122)
	at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:737)
	at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:370)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:314)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1162)
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1151)
	at server.Boot.main(Boot.java:13)

这样就找到了注入属性的位置,属性就是这样注入的。

 

© 著作权归作者所有

强子1985

强子1985

粉丝 898
博文 1321
码字总数 968755
作品 8
南京
架构师
私信 提问
Spring IOC 容器源码分析 - 创建原始 bean 对象

1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续。在上一篇文章中,我们从战略层面上领略了方法的全过程。本篇文章,我们就从战术的层面上,详细分析方法中的一个重要的调用,即...

coolblog.xyz
2018/06/06
0
0
sprintboot-learn(二)

Filter和Listener Listener 自定义自己的Listener,继承需要重写的监听器。 方式一:直接在自定义监听器上面添加注解@WebListener,但是单纯这样是不会被扫描到的(实测不能),所以我们需要加@...

lazy~
2018/10/12
0
0
Spring IOC 实现原理

Spring IOC 实现原理 IOC: Inversion of Control ,即 "控制反转" , 不是什么技术,而是一种思想。原先需要自行实例化的对象, 交给IOC容器去实现。那么控制反转,谁被控制? 谁被反转 ? 在...

起个名忒难
2018/05/17
0
0
【死磕 Spring】—– IOC 之构造函数实例化 bean

原文出自:http://cmsblogs.com 用于实例化 bean,它会根据不同情况选择不同的实例化策略来完成 bean 的初始化,主要包括: Supplier 回调: 工厂方法初始化: 构造函数自动注入初始化: 默认...

chenssy
2018/10/25
0
0
通过循环依赖问题彻底理解SpringIOC的精华

前言 你可能会有如下问题: 1、想看Spring源码,但是不知道应当如何入手去看,对整个Bean的流程没有概念,碰到相关问题也没有头绪如何下手 2、看过几遍源码,没办法彻底理解,没什么感觉,没...

Java填坑之路
2018/11/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mysql mysql常用的常用函数

1. 数学函数 函 数 作 用 ABS(x) 返回x的绝对值 CEIL(x),CEILIN(x) 返回不小于x的最小整数值 FLOOR(x) 返回不大于x的最大整数值 RAND() 返回0~1的随机数 RAND(x) 返回0~1的随机数,x值相同返...

edison_kwok
39分钟前
0
0
译:Spring Data Repository 不区分大小写查询

使用Spring Data Repository 不区分大小写查询 原文链接:https://www.baeldung.com/spring-data-case-insensitive-queries 作者:Shubhra Srivastava 译者:liululee 1. 概览 Spring Data ......

liululee
46分钟前
1
0
读书replay《maven实战》.1.20190526

前情提要 maven这个工具用了好久了,但是一直都用的迷迷糊糊的,没有对它进行过系统性的学习,只是知道一些常用的功能怎么实现,所以20190516这一天我从JD购买了徐晓斌老师所著的《maven实战...

wanxiangming
今天
2
0
真实项目案例实战——【状态设计模式】使用场景

什么是状态模式 状态模式允许一个对象在其内部状态改变的时候改变其行为。这个对象看上去就像是改变了它的类一样。 状态模式应用场景 1.一个对象的行为取决于它的状态,并且它必须在运行时刻根...

须臾之余
今天
2
0
Java 实现把字符串转换成整数【底层实现】

https://blog.csdn.net/zl18310999566/article/details/80263396

qimh
今天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部