欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

spring 官方文档的接口理解整理(一)Bean

程序员文章站 2022-03-18 13:42:31
...

这儿提供一个我实验的源代码地址(有注释,如有错误,欢迎留言^_^,实验是检验真理的唯一标准):https://github.com/flycat0112/springArt

一、IOC容器

下面接口的执行顺序:BeanNameAware -> BeanClassLoaderAware ->  BeanFactoryAware -> applyBeanPostProcessorsBeforeInitialization -> invokeInitMethods -> applyBeanPostProcessorsAfterInitialization

/**
	 * 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, @Nullable RootBeanDefinition mbd) {
		if (System.getSecurityManager() != null) {
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				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;
	}

Ⅰ、自定义Bean的本质(对应项目的模块是spring-bean-lifecycle)

1、bean创建的时候做的操作(针对单个bean各自实现,不是所有bean):

org.springframework.beans.factory.InitializingBean   实现该接口,对bean创建之后做的操作。相等的注解:@PostConstruct

org.springframework.beans.factory.DisposableBean   实现该接口,对bean销毁前做的操作。相等的注解:@PreDestroy

ps:通过配置分别是init-method属性和destroy-method属性指定方法。设置默认的初始化方法和销毁方法可以通过配置中设置<Beans default-init-method="init"></Beans>这种形式。还有就是注解方式,通过实现接口方式,还有配置方式三种可以同时存在,他们的顺序是:先是注解,其次通过接口、最后是配置。

2、Bean的时间周期操作(针对所有单个Bean各自实现,但是,系统启动和结束才能调用,不受Bean的创建再次执行

org.springframework.context.Lifecycle    其中申明了三个方法start(), stop(),isRunning()三个方法。isRunning方法是决定stop方法是否执行,返回true会执行。

org.springframework.context.Phased    其中申明了一个getPhase方法,这个方法是为了控制bean的初始化顺序和销毁的顺序,返回数字小的先初始化。通过Collections.sort(keys)来排序,进而控制执行顺序的。

org.springframework.context.SmartLifecycle    该加接口实现了Lifecycle和phased接口,宁外新加了isAutoStartup(), stop(Runnable run)两个方法。第一个方法如果返回true,spring容器刷新的时候就会执行start方法;第二个方法和Lifecycle不同提供run是因为提供一个有序地或者并发(多线程)的支持

ps:上面的处理机制大概是这样,Lifecycle接口中stop方法是不会使用的,通常使用的SmartLifecycle接口额stop方法,这个处理机制只是org.springframework.context.LifecycleProcessor接口的默认实现org.springframework.context.support.DefaultLifecycleProcessor的实现机制。

3、LifecycleProcessor

org.springframework.context.LifecycleProcessor接口提供给ApplicationContext回调方法来刷新和关闭上下文(通过简单的委托的方式)

Ⅱ、Aware(对应项目的模块是spring-bean-aware)

org.springframework.context.ApplicationContextAware   中有setApplicationContext方法返回应用中当强使用的ApplicationContext接口的实现类。从其中获取查找我们想要的对象,写自己的方法,通过反射和业务代码解偶。

org.springframework.beans.factory.BeanNameAware  中有setBeanName方法返回当前实现的对象用key-value形式保存的spring容器中对应的key值。

ps:提供用户感知spring内部的对象。比如ApplicationContextAware提供ApplicationContext对象,BeanNameAware提供对象知道在spring容器里面保存对象的Key值(name)。spring-bena-aware的demo采用了应用实例,想通过委托的方式,方便地调用加密算法。

Ⅲ、容器拓展点(对应的模块spring-bean-expend)

org.springframework.beans.factory.config.BeanPostProcessor接口提供方法有postProcessBeforeInitialization,postProcessAfterInitialization两个。他们做操作是针对所有容器中的对象,不是只是针对本对象。ps: before方法在@PostConstruct、InitializingBean接口、init-method的对象执行之前,after在之后。源码调用情况查看开头源代码。

org.springframework.beans.factory.config.BeanFactoryPostProcessor 接口提供postProcessBeanFactory方法,针对创建Bean之前,只存在创建bean的配置文件,该接口可以对创建bean的参数进行修改,比如,对spring的jdbc配置里面使用参数(properties)文件,需要把值${}替换成参数文件里面对应的值,不能设置bean标签的属性,因为调用该对象前那个对象已经创建了。

org.springframework.beans.factory.FactoryBean接口提供一个创建Bean对象的工厂,方法有getObject,getObjectType,isSingleton。通过java代码创建复杂对象放到容器中。从容器中获取该对象只能通过“class”或者“注解”的方式从spring容器中获取对象,不能通过对象名称获取对象。

Ⅳ、spring注解(对应项目的模块是spring-bean-anntation)

@Required   设置set方法参数是否可以为null

@Primary   提升优先级

@Configuration 作用和@Component注解相同,但是@Configuration一般和@Bean一起用。

@Bean 功能和实现org.springframework.beans.factory.FactoryBean接口相似

@Autowired @Qualifier     确定详细的对象,@Autowired注解和@Resource注解的区别是,它要确定那个对象需要和@Qualifier来确定,并且,没有@Qualifier的话,默认通过类型来查找。

@Resource    默认通过变量名称来查找,如果变量是bean3,这儿找不到对象,报错。

@Scop   设置是单例,多例等

@DependsOn  设置bean的创建顺序。

ps:可以定义自己的基于@Qualifier注解作用相似的注解,用来详细确认一个对象来注入,可以自己定义其余的属性来确认。