广州市网站,公司网站推广计划书怎么做,南阳网(网站).,做一个网站的预算目录 Spring后处理器
Bean工厂后处理器-BeanFactoryPostProcessor
修改beanDefinition对象
添加beanDefiniton对象
方法一
方法二
自定义Component Spring后处理器
Spring后处理器是Spring对外开放的重要拓展点#xff08;让我们可以用添加自己的逻辑#xff09;…目录 Spring后处理器
Bean工厂后处理器-BeanFactoryPostProcessor
修改beanDefinition对象
添加beanDefiniton对象
方法一
方法二
自定义Component Spring后处理器
Spring后处理器是Spring对外开放的重要拓展点让我们可以用添加自己的逻辑允许我们介入到Bean的整个实例化流程中来以达到动态注册BeanDefinition向BeanDefitionMap中添加BeanDefition对象的过程动态修改BeanDefition以及动态修改Bean的作用。Spring主要有两种后处理器 BeanFactoryPostprocessorBean工厂后处理器执行时机在BeanDefinitionMap填充完毕Bean实例化之前执行BeanPostProcessorBean后处理器执行时机一般在Bean实例化后填充到单例池singletonObjects之前执行
Bean工厂后处理器-BeanFactoryPostProcessor
BeanFactoryPostProcessor是一个接口规范实现该接口的类只要交由Spring容器管理即在配置文件中注册该类称为Bean对象的话那么Spring就会回调该接口的方法用于对BeanDefition注册和修改功能BeanFactoryPostProcessor定义如下 //
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.beans.factory.config;import org.springframework.beans.BeansException;FunctionalInterface
public interface BeanFactoryPostProcessor {void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
}修改beanDefinition对象 创建一个实现类修改beanDefinition对象 package com.example.PostProcessor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {System.out.println(beanDefinitionMap填充完毕后会回调该方法);// todo 修改Map集合中的BeanDefinition对象BeanDefinition userService beanFactory.getBeanDefinition(userService);userService.setBeanClassName(com.example.DAO.Impl.UserDAOImpl);}
}测试类 package com.example.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestApplicationContext {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);System.out.println(context.getBean(userService));}
}运行结果如下 显然bean对应的类被改变了
添加beanDefiniton对象
方法一
创建一个类添加beanDefiniton对象 package com.example.PostProcessor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {// todo 向Map集合中添加一个BeanDefinition对象即在配置文件中没有注册// 创建一个新的beanDefinition对象BeanDefinition beanDefinition new RootBeanDefinition();// 设置bean对应的类beanDefinition.setBeanClassName(com.example.DAO.Impl.UserDAOImpl);DefaultListableBeanFactory listableBeanFactory (DefaultListableBeanFactory) beanFactory;// 添加该beanDefinition对象listableBeanFactory.registerBeanDefinition(UserDAO, beanDefinition);}
}在配置文件中没有配置UserDAO了 测试类 package com.example.Test;import com.example.DAO.Impl.UserDAOImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestApplicationContext {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);System.out.println(context.getBean(UserDAOImpl.class));}
}运行结果 beanDefinition对象成功添加 方法二
Spring提供了一个BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor专门用于注册BeanDefinition操作 //
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//package org.springframework.beans.factory.support;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}创建一个类实现后处理器BeanFactoryPostProcessor的子接口BeanDefinitionRegistryPostProcessor记得将该类注册到Spring容器中 package com.example.PostProcessor;import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.beans.factory.support.RootBeanDefinition;public class MyBeanFactoryPostProcessor02 implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 注册beanDefinitionBeanDefinition beanDefinition new RootBeanDefinition();beanDefinition.setBeanClassName(com.example.DAO.Impl.UserDAOImpl);registry.registerBeanDefinition(UserDAO, beanDefinition);}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}实现添加beanDefiniton就会简单很多 测试类 package com.example.Test;import com.example.DAO.Impl.UserDAOImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestApplicationContext {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);System.out.println(context.getBean(UserDAOImpl.class));}
}运行结果如下
完整流程图 自定义Component
案例 使用Spring的BeanFactoryPostProcessor扩展点完成自定义注解扫描要求 自定义MyComponent注解使用在类上使用资料中提供好的包扫描工具BaseClassScanUtils完成指定包的类扫描 工具类链接如下https://hkm-web.oss-cn-beijing.aliyuncs.com/Utils自定义BeanFactoryPostProcessor完成注解MyComponent的解析解析最终被Spring管理具体代码如下 注解类 package com.example.Anno;import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;Target(ElementType.TYPE) // 设该注解的使用范围
Retention(RetentionPolicy.RUNTIME) // 设置该注解运行期间可见
public interface MyComponent {String value(); //用于设置注解的值
}工具类 package com.example.Utils;import com.example.Anno.MyComponent;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.util.ClassUtils;import java.util.HashMap;
import java.util.Map;public class BaseClassScanUtils {//设置资源规则private static final String RESOURCE_PATTERN /**/*.class;public static MapString, Class scanMyComponentAnnotation(String basePackage) {//创建容器存储使用了指定注解的Bean字节码对象MapString, Class annotationClassMap new HashMapString, Class();//spring工具类可以获取指定路径下的全部类ResourcePatternResolver resourcePatternResolver new PathMatchingResourcePatternResolver();try {String pattern ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX ClassUtils.convertClassNameToResourcePath(basePackage) RESOURCE_PATTERN;Resource[] resources resourcePatternResolver.getResources(pattern);//MetadataReader 的工厂类MetadataReaderFactory refractory new CachingMetadataReaderFactory(resourcePatternResolver);for (Resource resource : resources) {//用于读取类信息MetadataReader reader refractory.getMetadataReader(resource);//扫描到的classString classname reader.getClassMetadata().getClassName();Class? clazz Class.forName(classname);//判断是否属于指定的注解类型if(clazz.isAnnotationPresent(MyComponent.class)){//获得注解对象MyComponent annotation clazz.getAnnotation(MyComponent.class);//获得属value属性值String beanName annotation.value();//判断是否为if(beanName!null!beanName.equals()){//存储到Map中去annotationClassMap.put(beanName,clazz);continue;}//如果没有为,那就把当前类的类名作为beanNameannotationClassMap.put(clazz.getSimpleName(),clazz);}}} catch (Exception exception) {}return annotationClassMap;}public static void main(String[] args) {MapString, Class stringClassMap scanMyComponentAnnotation(com.itheima);System.out.println(stringClassMap);}
}使用注解来注册为Bean对象的类 package com.example.Beans;import com.example.Anno.MyComponent;MyComponent(otherBean)
public class otherBeans {
}在配置文件中没有配置该类作为bean对象 后工厂处理器类该类要交给Spring容器管理 package com.example.PostProcessor;import com.example.Utils.BaseClassScanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;import java.util.Map;public class MyComponentBeanFactoryProcessor implements BeanDefinitionRegistryPostProcessor {Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {// 通过工具去扫描指定包及其子包下的所有类收集使用MyComponent注解的类放在Map集合中MapString, Class MyComponentAnnotationMap BaseClassScanUtils.scanMyComponentAnnotation(com.example);// 遍历Map组装BeanDefinition进行注册MyComponentAnnotationMap.forEach((beanName,clazz)-{// 获取beanClassNameString beanClassName clazz.getName();// 创建beanDefinitionBeanDefinition beanDefinition new RootBeanDefinition();beanDefinition.setBeanClassName(beanClassName);// 注册registry.registerBeanDefinition(beanName,beanDefinition);});}Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}通过后工厂处理器类来将标记了自己创建的MyComponent注解的类创建为beanDefinition对象后添加到beanDefinitionMap集合中。 测试类 package com.example.Test;import com.example.Beans.otherBeans;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class TestApplicationContext {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(application.xml);System.out.println(context.getBean(otherBeans.class));}
}运行结果 运行成功~ 使用注解注册bean的原理 最主要是通过Bean工厂后处理器进行实现的通过工具类获取到添加了注解的类的集合后在后处理器中对扫描结果进行遍历然后生成对对应的beanDefinition对象后注册到beanDefinitonMap集合后即可。