网站如何做自适应,发不了软文的网站怎么做关键词优化,做网站需要备注号码,网站做数据分析的意义序言
前几篇文章详细介绍了Spring中实例化Bean的各种方式#xff0c;其中包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor以及构造器方式创建对象。
创建对象 这里再来简单回顾一下对象的创建#xff0c;不知道大家有没有这样一个疑…序言
前几篇文章详细介绍了Spring中实例化Bean的各种方式其中包括采用FactoryBean的方式创建对象、使用反射创建对象、自定义BeanFactoryPostProcessor以及构造器方式创建对象。
创建对象 这里再来简单回顾一下对象的创建不知道大家有没有这样一个疑问为什么创建对象之前要获取实例策略的意义在哪 因为我们在createBeanInstance()中调用instantiateBean()方法进行类的实例化创建时会有很多种选择 。根据构造器、工厂方法、参数…等等而其中一部分是采用Cglib动态代理的方式实例化其中一部分就是普通的Simple实例化。
SimpleInstantiationStrategy 而我们看到SimpleInstantiationStrategy类中方法就会方法类中共有3个instantiate()同名方法而每个方法传递的参数也大不一样根据参数就可判断出是根据不同的条件来创建对象构造器、工厂方法…
public class SimpleInstantiationStrategy implements InstantiationStrategy {Overridepublic Object instantiate(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner) {// 省略方法逻辑}protected Object instantiateWithMethodInjection(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner) {throw new UnsupportedOperationException(Method Injection not supported in SimpleInstantiationStrategy);}Overridepublic Object instantiate(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner,final Constructor? ctor, Object... args) {// 省略方法逻辑}protected Object instantiateWithMethodInjection(RootBeanDefinition bd, Nullable String beanName,BeanFactory owner, Nullable Constructor? ctor, Object... args) {throw new UnsupportedOperationException(Method Injection not supported in SimpleInstantiationStrategy);}Overridepublic Object instantiate(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner,Nullable Object factoryBean, final Method factoryMethod, Object... args) {// 省略方法体}
}而继承CglibSubclassingInstantiationStrategy了SimpleInstantiationStrategy因为在Simple类中已经对instantiate()进行了三种不同的实现所以在Cglib中没对instantiate()做额外处理而是实现了instantiateWithMethodInjection方法。 但底层调用的也是instantiate()并根据构造器来判断具体的实现方式。
public class CglibSubclassingInstantiationStrategy extends SimpleInstantiationStrategy {Overrideprotected Object instantiateWithMethodInjection(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner) {return instantiateWithMethodInjection(bd, beanName, owner, null);}Overrideprotected Object instantiateWithMethodInjection(RootBeanDefinition bd, Nullable String beanName, BeanFactory owner,Nullable Constructor? ctor, Object... args) {// Must generate CGLIB subclass...return new CglibSubclassCreator(bd, owner).instantiate(ctor, args);}// 省略部分源码public Object instantiate(Nullable Constructor? ctor, Object... args) {//根据beanDefinition创建一个动态生成的子类Class? subclass createEnhancedSubclass(this.beanDefinition);Object instance;// 如果构造器等于空那么直接通过反射来实例化对象if (ctor null) {instance BeanUtils.instantiateClass(subclass);}else {try {// 通过cglib对象来根据参数类型获取对应的构造器Constructor? enhancedSubclassConstructor subclass.getConstructor(ctor.getParameterTypes());// 通过构造器来获取对象instance enhancedSubclassConstructor.newInstance(args);}// 省略部分源码}
} 所以Spring中获取实例话策略后共5种创建对象的方式。并且Spring中对象的创建也并不都是采用Cglib动态代理。 回顾完了对象的创建我们顺着代码的逻辑继续向下执行。 现在对象创建了但是我们还不知道对象的初始化init和销毁destroy方法是什么。接下来就是对这两个方法做处理。
测试类
Person类中省略了get、set和构造器方法。 而为什么不用Init注解来表示初始化方法 因为Spring中并没有提供下面的两个注解是Java提供的元注解优先于Init方法执行。
public class Person {private String name;private int age;PostConstructpublic void init(){System.out.println(执行init方法);}PreDestroypublic void destroy(){System.out.println(执行destroy方法);}
}mergePostProcessor.xml
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsdcontext:component-scan base-packageorg.springframework.mergePostProcessor/context:component-scanbean idperson classorg.springframework.mergePostProcessor.Personproperty namename value张三/propertyproperty nameage value18/property/bean
/beansmain
public class TestMergePostProcessor {public static void main(String[] args) {ClassPathXmlApplicationContext ac new ClassPathXmlApplicationContext(mergePostProcessor.xml);Person person ac.getBean(person, Person.class);ac.close();}
}mergeBeanDefinitionPostProcessor
让我们把视线拉回到doCreateBean()中。 此时我们已经通过createBeanInstance()完成了对象的实例化操作。
protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.//这个beanWrapper是用来持有创建出来的bean对象的BeanWrapper instanceWrapper null;//如果是单例对象从factoryBeanInstanceCache缓存中移除该信息if (mbd.isSingleton()) {// 如果是单例对象从factoryBean实例缓存中移除当前bean定义信息instanceWrapper this.factoryBeanInstanceCache.remove(beanName);}// 没有就创建实例if (instanceWrapper null) {// 根据执行bean使用对应的策略创建新的实例如工厂方法构造函数主动注入、简单初始化instanceWrapper createBeanInstance(beanName, mbd, args);}//从包装类wrapped中获取原始的实例Object bean instanceWrapper.getWrappedInstance();//获取具体bean对象的classClass? beanType instanceWrapper.getWrappedClass();//如果不是NullBean类型则修改目标类型if (beanType ! NullBean.class) {mbd.resolvedTargetType beanType;}// Allow post-processors to modify the merged bean definition.//允许postProcessor修改合并的BeanDefinitionsynchronized (mbd.postProcessingLock) {// 如果没有执行过下面方法。if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException;}mbd.postProcessed true;}}// 省略部分源码} 获取BeanPostProcess并找到MergedBeanDefinitionPostProcessor类型的执行postProcessMergedBeanDefinition方法。
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);}}}先来看眼postProcessMergedBeanDefinition的继承关系。 postProcessMergedBeanDefinition()方法的实现有很多但是其中都有一个特点就是都是AnnotationBeanPostProcessor后缀所以都是对注解的处理。 而当我们Person对象加载、解析context:component-scan标签时就会将CommonAnnotationBeanPostProcessor注入到工厂中。所以在上面getBeanPostProcessors()调用时会获取到CommonAnnotationBeanPostProcessor并执行postProcessMergedBeanDefinition。 关于context:component-scan标签解析时如何进行组件的注册可看这篇帖子context: component-scan标签如何扫描、加载Bean。
CommonAnnotationBeanPostProcessor 当我们CommonAnnotationBeanPostProcessor实例创建时构造方法中会将PostConstruct.class和PreDestroy.class设置到属性中。
public class CommonAnnotationBeanPostProcessor extends InitDestroyAnnotationBeanPostProcessorimplements InstantiationAwareBeanPostProcessor, BeanFactoryAware, Serializable {public CommonAnnotationBeanPostProcessor() {setOrder(Ordered.LOWEST_PRECEDENCE - 3);setInitAnnotationType(PostConstruct.class);setDestroyAnnotationType(PreDestroy.class);ignoreResourceType(javax.xml.ws.WebServiceContext);}public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class? beanType, String beanName) {//处理PostConstruct 和 PreDestroy 注解super.postProcessMergedBeanDefinition(beanDefinition, beanType, beanName);InjectionMetadata metadata findResourceMetadata(beanName, beanType, null);metadata.checkConfigMembers(beanDefinition);}} 方法首先会调用父类中InitDestroyAnnotationBeanPostProcessor的postProcessMergedBeanDefinition方法。
postProcessMergedBeanDefinition 获取生命周期元数据信息并保存
public void postProcessMergedBeanDefinition(RootBeanDefinition beanDefinition, Class? beanType, String beanName) {//获取生命周期元数据信息并保存LifecycleMetadata metadata findLifecycleMetadata(beanType);metadata.checkConfigMembers(beanDefinition);}findLifecycleMetadata 依然是先从缓存中获取获取不到则构建LifecycleMetadata对象并放到缓存中。
private LifecycleMetadata findLifecycleMetadata(Class? clazz) {//如果生命周期元数据缓存为空则直接构建生命周期元数据 (默认创建了一个ConCurrentHashMap)if (this.lifecycleMetadataCache null) {// Happens after deserialization, during destruction...return buildLifecycleMetadata(clazz);}// Quick check on the concurrent map first, with minimal locking.//快速检查生命周期元数据缓存如果没有则构建生命周期元数据LifecycleMetadata metadata this.lifecycleMetadataCache.get(clazz);//缓存中不存在if (metadata null) {//双层锁防止多线程重复执行synchronized (this.lifecycleMetadataCache) {//再次从缓存中获取metadata this.lifecycleMetadataCache.get(clazz);if (metadata null) {//构建生命周期元数据metadata buildLifecycleMetadata(clazz);//将构建好的数据放入缓存中this.lifecycleMetadataCache.put(clazz, metadata);}return metadata;}}return metadata;}buildLifecycleMetadata 将 init 方法和 destroy 方法分类如果父类中也包含注解则循环处理。 因为会优先执行父类初始化方法 所以 init 放入集合时会放在 index 0 的位置。
private LifecycleMetadata buildLifecycleMetadata(final Class? clazz) {//是否包含PostConstruct注解和PreDestroy注解if (!AnnotationUtils.isCandidateClass(clazz, Arrays.asList(this.initAnnotationType, this.destroyAnnotationType))) {return this.emptyLifecycleMetadata;}//声明初始化方法集合ListLifecycleElement initMethods new ArrayList();//声明销毁方法集合ListLifecycleElement destroyMethods new ArrayList();//目标类型Class? targetClass clazz;do {//保存当前正在处理的方法final ListLifecycleElement currInitMethods new ArrayList();final ListLifecycleElement currDestroyMethods new ArrayList();// 反射获取当前类中的所有方法并依次对其调用第二个参数的lambda表达式ReflectionUtils.doWithLocalMethods(targetClass, method - {//当前方法包含initAnnotationType注解时(PostConstruct)if (this.initAnnotationType ! null method.isAnnotationPresent(this.initAnnotationType)) {//封装成LifecycleElement对象添加到currInitMethods集合中LifecycleElement element new LifecycleElement(method);currInitMethods.add(element);}// 当前方法包含destroyAnnotationType注解时(PreDestroy)if (this.destroyAnnotationType ! null method.isAnnotationPresent(this.destroyAnnotationType)) {//封装成LifecycleElement对象添加到currDestroyMethods集合中currDestroyMethods.add(new LifecycleElement(method));}});//每次都将currInitMethods集合中的元素添加到initMethods集合最前面// 因为可能父类中也包含PostConstruct注解的方法所以需要先执行父类的方法initMethods.addAll(0, currInitMethods);//放入destroyMethod的总集合中destroyMethods.addAll(currDestroyMethods);//获取父类targetClass targetClass.getSuperclass();}//如果父类不是Object.class则继续循环while (targetClass ! null targetClass ! Object.class);//如果集合为空则返回一个空的LifecycleMetadata对象否则封装并返回一个LifecycleMetadata对象return (initMethods.isEmpty() destroyMethods.isEmpty() ? this.emptyLifecycleMetadata :new LifecycleMetadata(clazz, initMethods, destroyMethods));}而当我们处理完后会进行检查并放入beanDefinition中等待执行。
public void checkConfigMembers(RootBeanDefinition beanDefinition) {SetLifecycleElement checkedInitMethods new LinkedHashSet(this.initMethods.size());for (LifecycleElement element : this.initMethods) {String methodIdentifier element.getIdentifier();if (!beanDefinition.isExternallyManagedInitMethod(methodIdentifier)) {// 注册初始化调用方法beanDefinition.registerExternallyManagedInitMethod(methodIdentifier);checkedInitMethods.add(element);}}SetLifecycleElement checkedDestroyMethods new LinkedHashSet(this.destroyMethods.size());for (LifecycleElement element : this.destroyMethods) {String methodIdentifier element.getIdentifier();if (!beanDefinition.isExternallyManagedDestroyMethod(methodIdentifier)) {// 注册销毁调用方法beanDefinition.registerExternallyManagedDestroyMethod(methodIdentifier);checkedDestroyMethods.add(element);}}this.checkedInitMethods checkedInitMethods;this.checkedDestroyMethods checkedDestroyMethods;}执行完成后beanDefinition中也有了待执行的初始化方法和销毁方法。 因为整个Bean的实例化、加载过程只有BeanDefinition是伴随始终的所以处理完之后要设置到BD中也正好印证了方法上的那个注释允许postProcessor修改合并的BeanDefinition