spring Bean的初始化过程解析

AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

使用BeanPostProcessor收集带有注解的方法和属性,方便下面初始化时调用。
org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors

protected void applyMergedBeanDefinitionPostProcessors(RootBeanDefinition mbd, Class<?> beanType, String beanName) {
	for (BeanPostProcessor bp : getBeanPostProcessors()) {
		if (bp instanceof MergedBeanDefinitionPostProcessor) {
			MergedBeanDefinitionPostProcessor bdp = (MergedBeanDefinitionPostProcessor) bp;
			bdp.postProcessMergedBeanDefinition(mbd, beanType, beanName);
		}
	}
}

这里的BeanPostProcessor主要有以下两个:

  • AutowiredAnnotationBeanPostProcessor:负责@Autowired、@Value
  • CommonAnnotationBeanPostProcessor:负责@Resource、@PostConstruct、@PreDestroy

AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

AutowiredAnnotationBeanPostProcessor负责@Autowired、@Value注解的方法和属性的收集。

org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor#buildAutowiringMetadata

private InjectionMetadata buildAutowiringMetadata(final Class<?> clazz) {
	// autowiredAnnotationTypes是在构造方法中被初始化的
	// autowiredAnnotationTypes @Autowired @Value
	if (!AnnotationUtils.isCandidateClass(clazz, this.autowiredAnnotationTypes)) {
		return InjectionMetadata.EMPTY;
	}
	List<InjectionMetadata.InjectedElement> elements = new ArrayList<>();
	Class<?> targetClass = clazz;
	do {
		final List<InjectionMetadata.InjectedElement> currElements = new ArrayList<>();
		// 查找带有@Autowired注解的属性
		ReflectionUtils.doWithLocalFields(targetClass, field -> {
			MergedAnnotation<?> ann = findAutowiredAnnotation(field);
			if (ann != null) {
				if (Modifier.isStatic(field.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static fields: " + field);
					}
					return;
				}
				boolean required = determineRequiredStatus(ann);
				currElements.add(new AutowiredFieldElement(field, required));
			}
		});
		// 查找带有@Autowired注解的方法
		ReflectionUtils.doWithLocalMethods(targetClass, method -> {
			Method bridgedMethod = BridgeMethodResolver.findBridgedMethod(method);
			if (!BridgeMethodResolver.isVisibilityBridgeMethodPair(method, bridgedMethod)) {
				return;
			}
			MergedAnnotation<?> ann = findAutowiredAnnotation(bridgedMethod);
			if (ann != null && method.equals(ClassUtils.getMostSpecificMethod(method, clazz))) {
				if (Modifier.isStatic(method.getModifiers())) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation is not supported on static methods: " + method);
					}
					return;
				}
				if (method.getParameterCount() == 0) {
					if (logger.isInfoEnabled()) {
						logger.info("Autowired annotation should only be used on methods with parameters: " +
								method);
					}
				}
				boolean required = determineRequiredStatus(ann);
				PropertyDescriptor pd = BeanUtils.findPropertyForMethod(bridgedMethod, clazz);
				currElements.add(new AutowiredMethodElement(method, required, pd));
			}
		});
		elements.addAll(0, currElements);
		targetClass = targetClass.getSuperclass();
	}
	while (targetClass != null && targetClass != Object.class);
	return InjectionMetadata.forElements(elements, clazz);
}

CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

CommonAnnotationBeanPostProcessor负责@Resource、@PostConstruct、@PreDestroy注解的方法和属性的收集,收集过程与AutowiredAnnotationBeanPostProcessor的收集过程类似。

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition

public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class<?> beanType, String beanName) {
	// 构造方法会注入@PostConstruct、@PreDestroy
	// 父类会查找带有@PostConstruct、@PreDestroy注解的方法
	super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);
	// 查找带有@Resource注解的属性和方法
	InjectionMetadata metadata = findResourceMetadata(beanName, beanType, null);
	metadata.checkConfigMembers(beanDefinition);
}

AbstractAutowireCapableBeanFactory#populateBean

调用各个BeanPostProcessor.postProcessProperties对属性进行设置。

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean

protected void populateBean(String beanName, RootBeanDefinition mbd, @Nullable BeanWrapper bw) {
	... ...
	if (hasInstAwareBpps) {
		if (pvs == null) {
			pvs = mbd.getPropertyValues();
		}
		for (BeanPostProcessor bp : getBeanPostProcessors()) {
			if (bp instanceof InstantiationAwareBeanPostProcessor) {
				InstantiationAwareBeanPostProcessor ibp = (InstantiationAwareBeanPostProcessor) bp;
				// 调用各个BeanPostProcessor.postProcessProperties对属性进行设置
				/**
				 * AutowiredAnnotationBeanPostProcessor处理@Autowired
				 * CommonAnnotationBeanPostProcessor处理@Resource
				 *
				 * @see AutowiredAnnotationBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String)
				 * @see org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties(org.springframework.beans.PropertyValues, java.lang.Object, java.lang.String)
				 */
				PropertyValues pvsToUse = ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);

	... ...
}

CommonAnnotationBeanPostProcessor#postProcessProperties

对带有@Resource注解的属性进行设置,对带有@Resource注解的方法进行调用。

org.springframework.context.annotation.CommonAnnotationBeanPostProcessor#postProcessProperties

public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
	// 上面的方法postProcessMergedBeanDefinition向缓存中设置了@PostConstruct、@PreDestroy注解的方法,@Resource注解的属性和方法
	// 这里会从缓存中取出对这些属性进行设置,方法进行调用
	InjectionMetadata metadata = findResourceMetadata(beanName, bean.getClass(), pvs);
	try {
		/**
		 * @see org.springframework.beans.factory.annotation.InjectionMetadata#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues)
		 */
		metadata.inject(bean, beanName, pvs);
	}
	catch (Throwable ex) {
		throw new BeanCreationException(beanName, "Injection of resource dependencies failed", ex);
	}
	return pvs;
}

AutowiredAnnotationBeanPostProcessor#postProcessProperties方法也是如此,对带有@Autowired注解的属性进行设置,对带有@Autowired注解的方法进行调用。

InjectionMetadata#inject

org.springframework.beans.factory.annotation.InjectionMetadata#inject

public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
	Collection<InjectedElement> checkedElements = this.checkedElements;
	Collection<InjectedElement> elementsToIterate =
			(checkedElements != null ? checkedElements : this.injectedElements);
	if (!elementsToIterate.isEmpty()) {
		for (InjectedElement element : elementsToIterate) {
			/**
			 * CommonAnnotationBeanPostProcessor注入的是InjectionMetadata.InjectedElement对象
			 * @see InjectedElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues)
			 *
			 * AutowiredAnnotationBeanPostProcessor注入的是AutowiredFieldElement和AutowiredMethodElement
			 * @see AutowiredAnnotationBeanPostProcessor.AutowiredFieldElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues)
			 * @see AutowiredAnnotationBeanPostProcessor.AutowiredMethodElement#inject(java.lang.Object, java.lang.String, org.springframework.beans.PropertyValues)
			 */
			element.inject(target, beanName, pvs);
		}
	}
}

InjectedElement的调用主要是反射进行属性的设置和方法的调用,如果属性是引用类型,将会触发beanFactory.getBean()方法从Spring容器中获取对象。

AbstractAutowireCapableBeanFactory#initializeBean

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#initializeBean(java.lang.String, java.lang.Object, org.springframework.beans.factory.support.RootBeanDefinition)

上面的populateBean()完成了对象的初始化,下面将会调用对象的初始化方法完成最后的初始化过程。

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {
	if (System.getSecurityManager() != null) {
		AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
			invokeAwareMethods(beanName, bean);
			return null;
		}, getAccessControlContext());
	}
	else {
		// 调用aware方法
		// BeanNameAware/BeanClassLoaderAware/BeanFactoryAware对应的setXxx方法
		invokeAwareMethods(beanName, bean);
	}
	Object wrappedBean = bean;
	if (mbd == null || !mbd.isSynthetic()) {
		// 处理EnvironmentAware/EmbeddedValueResolverAware/ResourceLoaderAware/
		// ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware
		// 处理@PostConstruct
		wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
	}
	try {
		// InitializingBean.afterPropertiesSet()
		// 调用init-method
		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()) {
		// AOP代理入口
		wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
	}
	return wrappedBean;
}

AbstractAutowireCapableBeanFactory#invokeAwareMethods

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeAwareMethods

这里只完成了BeanNameAware、BeanClassLoaderAware、BeanFactoryAware接口的初始化方法调用,还有部分aware接口将通过下面的BeanPostProcessor完成调用。

private void invokeAwareMethods(String beanName, 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);
		}
	}
}

AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyBeanPostProcessorsBeforeInitialization

public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
		throws BeansException {
	Object result = existingBean;
	for (BeanPostProcessor processor : getBeanPostProcessors()) {
		/**
		 * ApplicationContextAwareProcessor调用EnvironmentAware/EmbeddedValueResolverAware/ResourceLoaderAware/
		 * ApplicationEventPublisherAware/MessageSourceAware/ApplicationContextAware
		 *
		 * ImportAwareBeanPostProcessor调用ImportAware(Bean不仅需要实现ImportAware接口,还要有@Import注解)
		 * InitDestroyAnnotationBeanPostProcessor 处理@PostConstruct
		 *
		 * @see org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
		 * @see org.springframework.context.annotation.ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
		 * @see org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
		 */
		Object current = processor.postProcessBeforeInitialization(result, beanName);
		if (current == null) {
			return result;
		}
		result = current;
	}
	return result;
}

ApplicationContextAwareProcessor#postProcessBeforeInitialization

ApplicationContextAwareProcessor负责EnvironmentAware、EmbeddedValueResolverAware、ResourceLoaderAware、ApplicationEventPublisherAware、MessageSourceAware、ApplicationContextAware接口的调用。

org.springframework.context.support.ApplicationContextAwareProcessor#postProcessBeforeInitialization

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<Object>) () -> {
			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);
	}
}

ImportAwareBeanPostProcessor#postProcessBeforeInitialization

ImportAwareBeanPostProcessor主要负责ImportAware接口的调用。

ImportAware的具体使用如下:

ImportAwareBean.java

package com.morris.spring.entity.imports;

import org.springframework.context.annotation.ImportAware;
import org.springframework.core.type.AnnotationMetadata;

public class ImportAwareBean implements ImportAware {
	@Override
	public void setImportMetadata(AnnotationMetadata importMetadata) {
		// 在这里可以拿到注入ImportAwareBean的类ImportConfig上的注解@Transactional
		System.out.println(importMetadata.getAnnotationTypes());
	}
}

ImportConfig.java

package com.morris.spring.config;

import com.morris.spring.entity.imports.ImportAwareBean;
import org.springframework.context.annotation.Import;
import org.springframework.transaction.annotation.Transactional;
@Transactional
@Import(ImportAwareBean.class)
public class ImportConfig {
}

org.springframework.context.annotation.ConfigurationClassPostProcessor.ImportAwareBeanPostProcessor#postProcessBeforeInitialization

public Object postProcessBeforeInitialization(Object bean, String beanName) {
	if (bean instanceof ImportAware) {
		ImportRegistry ir = this.beanFactory.getBean(IMPORT_REGISTRY_BEAN_NAME, ImportRegistry.class);
		// bean必须通过@Import注解注入进来,importingClass才会有值
		AnnotationMetadata importingClass = ir.getImportingClassFor(ClassUtils.getUserClass(bean).getName());
		if (importingClass != null) {
			((ImportAware) bean).setImportMetadata(importingClass);
		}
	}
	return bean;
}

InitDestroyAnnotationBeanPostProcessor#postProcessBeforeInitialization

public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
	// LifecycleMetadata缓存数据从何来?
	// 前面在调用CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@Resource注解时,同时会调用
	// 父类InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@PostConstruct注解

	// 负责@PostConstruct方法的调用
	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;
}

LifecycleMetadata缓存数据从何来?前面在调用CommonAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@Resource注解时,同时会调用
父类InitDestroyAnnotationBeanPostProcessor#postProcessMergedBeanDefinition收集@PostConstruct注解。

而PostConstruct注解是在CommonAnnotationBeanPostProcessor的构造方法中指定的。

public CommonAnnotationBeanPostProcessor() {
	setOrder(Ordered.LOWEST_PRECEDENCE - 3);
	setInitAnnotationType(PostConstruct.class);
	setDestroyAnnotationType(PreDestroy.class);
	ignoreResourceType("javax.xml.ws.WebServiceContext");
}

AbstractAutowireCapableBeanFactory#invokeInitMethods

org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#invokeInitMethods

protected void invokeInitMethods(String beanName, 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<Object>) () -> {
					((InitializingBean) bean).afterPropertiesSet();
					return null;
				}, getAccessControlContext());
			}
			catch (PrivilegedActionException pae) {
				throw pae.getException();
			}
		}
		else {
			// 调用InitializingBean.afterPropertiesSet()
			((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)) {
			// 调用init-method
			invokeCustomInitMethod(beanName, bean, mbd);
		}
	}
}

@PostConstruct、afterPropertiesSet、init-method

@PostConstruct、InitializingBean.afterPropertiesSet、init-method这三者要实现的功能都是一致的,都是在bean实例化并初始化完成之后进行调用。

具体使用如下:

InitBean.java

package com.morris.spring.entity;

import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
public class InitBean implements InitializingBean {
	@PostConstruct
	public void postConstruct() {
		System.out.println("PostConstruct");
	}
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("afterPropertiesSet");
	public void init(){
		System.out.println("init");
}

InitDemo.java

package com.morris.spring.demo.annotation;

import com.morris.spring.entity.InitBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class InitDemo {
	@Bean(initMethod = "init")
	public InitBean initBean() {
		return new InitBean();
	}
	public static void main(String[] args) {
		new AnnotationConfigApplicationContext(InitDemo.class);
}

运行结果如下:

PostConstruct
afterPropertiesSet
init

运行结果与源码分析的一致,先执行PostConstruct,再执行afterPropertiesSet,最后initMethod。

注意这三种初始化方法都不能带有参数。

到此这篇关于spring Bean的初始化过程的文章就介绍到这了,更多相关spring Bean初始化内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • springboot中如何判断某个bean是否存在

    目录 如何判断某个bean是否存在 使用@Bean的好处与坏处 如何判断某个bean是否存在 ApplicationContext ctx = SpringUtil.getContext(); String[] beanNames = ctx.getBeanDefinitionNames(); Arrays.sort(beanNames); for (String beanName : beanNames) { //全部bean System.out.println(beanName); } /

  • springboot-启动bean冲突的解决

    目录 启动bean冲突 启动提示bean重复问题 先说结论 原理 启动bean冲突 在一次启动中遇到了bean冲突的问题,提示存在两个名称重复的bean org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [com.test.api.Application]; nested exception is org.springframework.conte

  • Spring Bean是如何初始化的详解

    目录 前言 三级缓存 doGetBean createBean doCreateBean instantiateBean instantiate instantiateClass 注入 AutowiredAnnotationBeanPostProcessor分析 postProcessProperties 如何实现bean注入的 总结 前言 做Java都有很多年了,一直有一个疑惑: Spring 如何初始化bean,怎么调用反射实例化对象的,自己动手来解除这个疑惑. 过去我认为spring be

  • 解决springboot生成bean名称冲突(AnnotationBeanNameGenerator)

    目录 springboot生成bean名称冲突 问题描述 解决问题 自定义bean对象重名问题 springboot生成bean名称冲突 问题描述 我们再使用springboot的时候,在不同的文件目录下,可能存在相同名称的java类,这个时候会报bean name冲突错误 首先我们来了解下,springboot生成bean名称的原理 当Component,Respository,Service,Controller注解的value树形没有自定义时,会根据类的名称生成一个短的bean name.

  • BeanDefinitionRegistryPostProcessor如何动态注册Bean到Spring

    目录 1.理论 2.实战代码 总结下 1.理论 一般如果想将类注册到spring容器,让spring来完成实例化,常用方式如下: xml中通过bean节点来配置: 使用@Service.@Controller.@Conponent等注解. 最近在研究通过Spring初始化时扫描自定义注解,查到了通过实现BeanDefinitionRegistryPostProcessor获取Bean,从而获得自定义注解. Spring支持我们通过代码来将指定的类注册到spring容器中. Spring容器初始化

  • spring Bean的初始化过程解析

    AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors 使用BeanPostProcessor收集带有注解的方法和属性,方便下面初始化时调用.org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#applyMergedBeanDefinitionPostProcessors protected void

  • Spring Bean实例化实现过程解析

    这篇文章主要介绍了Spring Bean实例化实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Bean的实例化 1.构造器实例化:Spring容器通过Bean对应类中默认的无参构造方法来实例化Bean package com.itheima.instance.constructor; public class Bean1 { } <?xml version="1.0" encoding="UTF-8&quo

  • Spring Boot整合Spring Cache及Redis过程解析

    这篇文章主要介绍了Spring Boot整合Spring Cache及Redis过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.安装redis a.由于官方是没有Windows版的,所以我们需要下载微软开发的redis,网址: https://github.com/MicrosoftArchive/redis/releases b.解压后,在redis根目录打开cmd界面,输入:redis-server.exe redis.wind

  • Spring整合MyBatis图示过程解析

    这篇文章主要介绍了Spring整合MyBatis图示过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.导入所需要的jar依赖 !--MyBatis和Spring的整合包 由MyBatis提供--> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <vers

  • SPRING IOC注入方式过程解析

    这篇文章主要介绍了SPRING IOC注入方式过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Spring IOC注入的方法主要有两种 1:设值注入 2:构造注入 简单来说一个是调用set方法设值,一个是通过构造函数设值 Spring-ioc.xml <?xml version= "1.0" encoding= "UTF-8"?> <beans xmlns= "http://ww

  • spring boot整合kafka过程解析

    这篇文章主要介绍了spring boot整合kafka过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一.启动kafka 启动kafka之前一定要启动zookeeper,因为要使用kafka必须要使用zookeeper. windows环境下启动,直接使用kafka自带的zookeeper: E:\kafka_2.12-2.4.0\bin\windows zookeeper-server-start.bat ..\..\config\z

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

    本文实例讲述了Spring Bean的初始化和销毁.分享给大家供大家参考,具体如下: 一 点睛 在开发过程中,经常遇到在Bean使用之前或者之后做一些必要的操作,Spring对Bean的生命周期的操作提供了支持. 1 Java配置方式:使用@Bean的initMethod和destroyMethod. 2 注解方式:利用JSR-250的@PostConstruct和@PreDestroy. 二 实战 1 增加JSR250支持 <dependency> <groupId>javax.

  • Spring Boot 整合 Druid过程解析

    这篇文章主要介绍了Spring Boot 整合 Druid过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 概述 Druid 是阿里巴巴开源平台上的一个项目,整个项目由数据库连接池.插件框架和 SQL 解析器组成.该项目主要是为了扩展 JDBC 的一些限制,可以让程序员实现一些特殊的需求,比如向密钥服务请求凭证.统计 SQL 信息.SQL 性能收集.SQL 注入检查.SQL 翻译等,程序员可以通过定制来实现自己需要的功能. Druid 是

  • Spring boot整合log4j2过程解析

    这篇文章主要介绍了Spring boot整合log4j2过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 以前整合过log4j2,但是今天再次整合发现都忘记了,而且也没有记下来 1.pom.xml中 (1)把spring-boot-starter-web包下面的spring-boot-starter-logging排除 <dependency> <groupId>org.springframework.boot</gr

  • Java静态和非静态成员变量初始化过程解析

    这篇文章主要介绍了Java静态和非静态成员变量初始化过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 Java中非静态成员变量.静态成员变量的初始化时机. 非静态变量 我们在这里分析三种结构,着重分析这三种结构的初始化顺序: 成员变量初始化语句: 成员变量初始化块: 构造函数: 示例一: public class MyTest { private String name = "wei.hu"; public MyTest(Str

随机推荐