国外游戏网站设计,网站开发用怎么语言,石家庄互联网公司排行榜,化工企业网站jsp阶段8#xff1a;Bean属性设置阶段
属性设置阶段分为3个小的阶段
实例化后阶段Bean属性赋值前处理Bean属性赋值
实例化后阶段 这里也有spring给我们预留了扩展#xff0c;就是实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法#xff0c;开发…阶段8Bean属性设置阶段
属性设置阶段分为3个小的阶段
实例化后阶段Bean属性赋值前处理Bean属性赋值
实例化后阶段 这里也有spring给我们预留了扩展就是实现InstantiationAwareBeanPostProcessor的postProcessAfterInstantiation方法开发者实现这个接口重写此方法可以了 源码
for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp (InstantiationAwareBeanPostProcessor) bp;if (!ibp.postProcessAfterInstantiation(bw.getWrappedInstance(), beanName)) {return;}}
}postProcessAfterInstantiation 方法返回false的时候后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了。 spring源码位置
default boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {return true;
}来个案例先建一个process
/*** description: 设置赋值前如果返回false将不会被赋值** 会调用 InstantiationAwareBeanPostProcessor 接口的 postProcessAfterInstantiation 这个方* 法调用逻辑如下* 后续的Bean属性赋值前处理、Bean* 属性赋值都会被跳过了。* author: stone* date: Created by 2021/3/25 20:25* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.setprop*/
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {/*** 后续的Bean属性赋值前处理、Bean* 属性赋值都会被跳过了。* param bean* param beanName* return* throws BeansException*/Overridepublic boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
// System.out.println(调用 MyInstantiationAwareBeanPostProcessor#postProcessAfterInstantiation);if (pig1.equalsIgnoreCase(beanName)) {return false;}return true;}再来一个spring bean
package com.shiguiwu.springmybatis.spring.lifecycle.definition;import com.shiguiwu.springmybatis.spring.lifecycle.instance.MyAutowire;
import lombok.Data;/*** description: 小猪* author: stone* date: Created by 2021/3/17 14:08* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.definition*/
Data
public class Pig {private String name;private Integer age;private String description;public Pig() {}MyAutowirepublic Pig(String name, Integer age) {System.out.println(增强候选注解MyAutowire );this.name name;this.age age;}public Pig(String name, Integer age, String description) {this.name name;this.age age;this.description description;}
}
测试案例如下
public class InstancedTests {public static void main(String[] args) {DefaultListableBeanFactory factory new DefaultListableBeanFactory();factory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());BeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(Pig.class).addPropertyValue(name, 猪八戒).addPropertyValue(age, 30).getBeanDefinition();BeanDefinition beanDefinition1 BeanDefinitionBuilder.genericBeanDefinition(Pig.class).addPropertyValue(name, 猪悟能).addPropertyValue(age, 35).getBeanDefinition();factory.registerBeanDefinition(pig, beanDefinition);factory.registerBeanDefinition(pig1, beanDefinition1);Arrays.stream(factory.getBeanDefinitionNames()).forEach(s - System.out.println(factory.getBean(s)));}
}打印结果
Connected to the target VM, address: 127.0.0.1:52046, transport: socket
20:22:20.387 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean pig
调用InstantiationAwareBeanPostProcessor #postProcessProperties
Pig(name猪无能, age12, descriptionnull)
20:22:20.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean pig1
Pig(namenull, agenull, descriptionnull)
Disconnected from the target VM, address: 127.0.0.1:52046, transport: socket被指定的bean名称跳过了属性赋值 Bean属性赋值前阶段 这个阶段spring照样为开发者预留了干涉spring bean赋值前阶段的操作这个阶段会调用 InstantiationAwareBeanPostProcessor 接口的postProcessProperties 方法调 用逻辑 代码如下
for (BeanPostProcessor bp : getBeanPostProcessors()) {if (bp instanceof InstantiationAwareBeanPostProcessor) {InstantiationAwareBeanPostProcessor ibp (InstantiationAwareBeanPostProcessor) bp;PropertyValues pvsToUse ibp.postProcessProperties(pvs, bw.getWrappedInstance(), beanName);if (pvsToUse null) {if (filteredPds null) {filteredPds filterPropertyDescriptorsForDependencyCheck(bw, mbd.allowCaching);}pvsToUse ibp.postProcessPropertyValues(pvs, filteredPds,bw.getWrappedInstance(), beanName);if (pvsToUse null) {return;}}pvs pvsToUse;}
}从上面可以看出如果 InstantiationAwareBeanPostProcessor 中的 postProcessProperties 和 postProcessPropertyValues 都返回空的时候表示这个bean不 需要设置属性直接返回了直接进入下一个阶段。 来看一下 postProcessProperties 这个方法的定义
Nullable
default PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {return pvs;
}PropertyValues中保存了bean实例对象中所有属性值的设置所以我们可以在这个这个方法中对PropertyValues值进行修改 示例代码如下
Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {System.out.println(调用InstantiationAwareBeanPostProcessor #postProcessProperties);if (beanName.equals(pig)) {if (pvsnull) {pvs new MutablePropertyValues();}if (pvs instanceof MutablePropertyValues) {MutablePropertyValues pv (MutablePropertyValues) pvs;//偷梁换柱给属性辅助pv.add(name, 猪无能);pv.add(age, 12);}}return null;
}Bean属性赋值阶段 这个过程比较简单了循环处理 PropertyValues 中的属性值信息通过反射调用set方法将属性的值设置到bean实例中。 PropertyValues中的值是通过bean xml中property元素配置的或者调用MutablePropertyValues中add方法设置的值。 阶段9Bean初始化阶段
这个阶段分为5个小的阶段
Bean Aware接口回调Bean初始化前操作Bean初始化操作Bean初始化后操作Bean初始化完成操作
Bean Aware接口回调,这里也是spring给我们的扩展 这块的源码
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);}}
}如果我们的bean实例实现了上面的接口会按照下面的顺序依次进行调用 BeanNameAware将bean的名称注入进去 BeanClassLoaderAware将BeanClassLoader注入进去 BeanFactoryAware将BeanFactory注入进去 来一个实现这三个接口的类
/*** description: 三个接口* author: stone* date: Created by 2021/3/28 11:54* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class MyAware implements BeanNameAware, BeanClassLoaderAware, BeanFactoryAware {Overridepublic void setBeanName(String name) {System.out.println(beanName: name);}Overridepublic void setBeanClassLoader(ClassLoader classLoader) {System.out.println(classLoader: classLoader);}Overridepublic void setBeanFactory(BeanFactory beanFactory) throws BeansException {System.out.println(beanFactory: beanFactory);}
}测试代码
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** description: 9.1初始化-aware接口回调* author: stone* date: Created by 2021/3/28 11:51* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class AwareTests {public static void main(String[] args) {DefaultListableBeanFactory factory new DefaultListableBeanFactory();BeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(MyAware.class).getBeanDefinition();factory.registerBeanDefinition(myAware, beanDefinition);System.out.println(factory.getBean(MyAware.class));}
}输出信息
Connected to the target VM, address: 127.0.0.1:55707, transport: socket
22:21:14.221 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean myAware
beanName:myAware
classLoader:sun.misc.Launcher$AppClassLoader18b4aac2
beanFactory:org.springframework.beans.factory.support.DefaultListableBeanFactory6c3f5566: defining beans [myAware]; root of factory hierarchy
com.shiguiwu.springmybatis.spring.lifecycle.init.MyAware71248c21
Disconnected from the target VM, address: 127.0.0.1:55707, transport: socketBean初始化前操作spring给开发者的扩展 这个阶段的源码
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;
}会调用 BeanPostProcessor的postProcessBeforeInitialization 方法若返回null当前方法将结束。 通常称postProcessBeforeInitialization这个方法为bean初始化前操作。 这个接口有2个实现类比较重要,画重点
org.springframework.context.support.ApplicationContextAwareProcessor
org.springframework.context.annotation.CommonAnnotationBeanPostProcessorApplicationContextAwareProcessor注入6个Aware接口对象 如果bean实现了下面的接口在ApplicationContextAwareProcessor#postProcessBeforeInitialization 中会依次调用下面接口中的方法将 Aware 前缀对应的对象注入到bean实例中。 EnvironmentAware注入Environment对象 EmbeddedValueResolverAware注入EmbeddedValueResolver对象 ResourceLoaderAware注入ResourceLoader对象 ApplicationEventPublisherAware注入ApplicationEventPublisher对象 MessageSourceAware注入MessageSource对象 ApplicationContextAware注入ApplicationContext对象 从名称上可以看出这个类以 ApplicationContext 开头的说明这个类只能在 ApplicationContext 环境中使用。
CommonAnnotationBeanPostProcessor调用PostConstruct标注的方法 CommonAnnotationBeanPostProcessor#postProcessBeforeInitialization 中会调用bean中所有标注PostConstruct注解的方法 整体来个案例
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringValueResolver;import javax.annotation.PostConstruct;/*** description: 初始化前操作* author: stone* date: Created by 2021/3/28 12:06* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class BeforeBean implements EnvironmentAware, EmbeddedValueResolverAware,ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware,ApplicationContextAware {PostConstructpublic void postConstruct1() {System.out.println(postConstruct1);}PostConstructpublic void postConstruct2() {System.out.println(postConstruct2);}Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {System.out.println(applicationContext applicationContext);}Overridepublic void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {System.out.println(applicationEventPublisher applicationEventPublisher);}Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {System.out.println(resolver resolver);}Overridepublic void setEnvironment(Environment environment) {System.out.println(environment environment);}Overridepublic void setMessageSource(MessageSource messageSource) {System.out.println(messageSource messageSource);}Overridepublic void setResourceLoader(ResourceLoader resourceLoader) {System.out.println(resourceLoader resourceLoader);}
}测试代码如下
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** description: 9.2初始化前* author: stone* date: Created by 2021/3/28 12:04* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class BeforeInitTests {public static void main(String[] args) {AnnotationConfigApplicationContext factory new AnnotationConfigApplicationContext();
// BeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(BeforeBean.class).getBeanDefinition();
// factory.(beforeBean, beanDefinition);factory.register(BeforeBean.class);factory.refresh();System.out.println(factory.getBean(BeforeBean.class));}
}打印结果
environmentStandardEnvironment {activeProfiles[], defaultProfiles ...
resolverorg.springframework.beans.factory.config.EmbeddedValueResolver3a52dba3
resourceLoaderorg.springframework.context.annotation.AnnotationConfigApplicationContext11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationEventPublisherorg.springframework.context.annotation.AnnotationConfigApplicationContext11438d26, started on Tue Nov 02 22:59:30 CST 2021
messageSourceorg.springframework.context.annotation.AnnotationConfigApplicationContext11438d26, started on Tue Nov 02 22:59:30 CST 2021
applicationContextorg.springframework.context.annotation.AnnotationConfigApplicationContext11438d26, started on Tue Nov 02 22:59:30 CST 2021
postConstruct1
postConstruct2
com.shiguiwu.springmybatis.spring.lifecycle.init.BeforeBean610f7aa大家可以去看一下AnnotationConfigApplicationContext的源码其内部会添加很多 BeanPostProcessor 到 DefaultListableBeanFactory 中。 Bean初始化阶段 2个步骤
调用InitializingBean接口的afterPropertiesSet方法调用定义bean的时候指定的初始化方法 调用InitializingBean接口的afterPropertiesSet方法
public interface InitializingBean {public void afterPropertiesSet() throws Exception;
}当我们的bean实现了这个接口的时候会在这个阶段被调用 调用bean定义的时候指定的初始化方法 方式1xml方式指定初始化方法
bean init-methodbean中方法名称/方式2Bean的方式指定初始化方法
Bean(initMethod 初始化的方法)方式3api的方式指定初始化方法
this.beanDefinition.setInitMethodName(methodName);初始化方法最终会赋值给下面这个字段 org.springframework.beans.factory.support.AbstractBeanDefinition#initMethodName 案例如下
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.InitializingBean;/*** description: 初始化bean* author: stone* date: Created by 2021/3/28 13:04* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class InitializeBean implements InitializingBean {public void init() {System.out.println(初始化方法);}Overridepublic void afterPropertiesSet() throws Exception {System.out.println(afterPropertiesSet);}
}测试代码
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** description: 9.3初始化阶段* author: stone* date: Created by 2021/3/28 13:02* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class InitializeTests {public static void main(String[] args) {DefaultListableBeanFactory factory new DefaultListableBeanFactory();BeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(InitializeBean.class).getBeanDefinition();beanDefinition.setInitMethodName(init);factory.registerBeanDefinition(initializeBean, beanDefinition);System.out.println(factory.getBean(InitializeBean.class));}
}输出结果
23:09:16.350 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory
afterPropertiesSet
初始化方法
com.shiguiwu.springmybatis.spring.lifecycle.init.InitializeBean221af3c0
socket调用顺序InitializingBean中的afterPropertiesSet、然后在调用自定义的初始化方法 Bean初始化后阶段
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {Object result existingBean;Object current;for(Iterator iterator this.getBeanPostProcessors().iterator(); iterator.hasNext(); result current) {BeanPostProcessor processor (BeanPostProcessor)iterator.next();current processor.postProcessAfterInitialization(result, beanName);if (current null) {return result;}}return result;
}调用 BeanPostProcessor接口的postProcessAfterInitialization方法 返回null的时候会中断上面的操作,注意这里也是扩展哦 通常称postProcessAfterInitialization这个方法为bean初始化后置操作。 来个案例
public class MyBeanPostProcessor implements BeanPostProcessor {Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {System.out.println(bean : beanName);System.out.println(初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》);return bean;}
}测试代码
package com.shiguiwu.springmybatis.spring.lifecycle.init;import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;/*** description: 9.4初始化后阶段* author: stone* date: Created by 2021/3/28 13:07* version: 1.0.0* pakeage: com.shiguiwu.springmybatis.spring.lifecycle.init*/
public class AfterInitializeTests {public static void main(String[] args) {DefaultListableBeanFactory factory new DefaultListableBeanFactory();//叫一个初始化后处理器factory.addBeanPostProcessor(new MyBeanPostProcessor());AbstractBeanDefinition beanDefinition BeanDefinitionBuilder.genericBeanDefinition(String.class).addConstructorArgValue( shiguiwu).getBeanDefinition();AbstractBeanDefinition beanDefinition1 BeanDefinitionBuilder.genericBeanDefinition(Integer.class).addConstructorArgValue(15).getBeanDefinition();factory.registerBeanDefinition(shiguiwuabc, beanDefinition);factory.registerBeanDefinition(shiguiwuA, beanDefinition1);System.out.println(factory.getBean(String.class));System.out.println(factory.getBean(Integer.class));}
}输出结果
Connected to the target VM, address: 127.0.0.1:56910, transport: socket
23:20:37.770 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean shiguiwuabc
bean :shiguiwuabc
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
shiguiwu
23:20:38.099 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean shiguiwuA
bean :shiguiwuA
初始化后》》》》》》》》》》》》》》》》》》》》》》》》》》》》》》
15
Disconnected from the target VM, address: 127.0.0.1:56910, transport: socketProcess finished with exit code 0此致终篇完毕内容有点希望能好好消化接下来就是尾篇。