您现在的位置是:主页 > news > 网页制作个人简历教程/青岛网站建设方案优化
网页制作个人简历教程/青岛网站建设方案优化
admin2025/6/18 0:32:38【news】
简介网页制作个人简历教程,青岛网站建设方案优化,网站开发需求报告模板下载,ui设计可以在ipad上面做嘛?在探究springboot默认注解扫描的过程中发现,在ConfigurationClassParser中除了对组件扫描进行处理,还对PropertySource、Import、ImportResource、Bean等注解进行处理。 下面来看看Import注解的作用和它的源码。 文章目录一、前期准备1.1 创建工程1.2 创…
在探究springboot默认注解扫描的过程中发现,在ConfigurationClassParser中除了对组件扫描进行处理,还对@PropertySource、@Import、@ImportResource、@Bean等注解进行处理。
下面来看看@Import注解的作用和它的源码。
文章目录
- 一、前期准备
- 1.1 创建工程
- 1.2 创建文件
- 1.3 说明
- 1.4 总结
- 二、引入配置类过程探究
- 2.1 配置类的解析
- 2.2 getImports(sourceClass)
- 2.3 processImports()
- 2.4 结论
- 三、ImportSelector探究
- 3.1 修改项目
- 3.2 探究源码
- 3.2.1 回顾配置类解析
- 3.2.2 processImports()
- 3.2.3 asSourceClasses()
- 3.2.4 processConfigurationClass()
- 3.2.5 processConfigBeanDefinitions()
- 3.3 总结
- 四、ImportBeanDefinitionRegistrar探究
- 4.1 低级用法
- 4.2 中级用法
- 4.3 高级用法
- 参考视频:https://www.bilibili.com/video/BV1Bq4y1Q7GZ?p=6
- 通过视频的学习和自身的理解整理出的笔记。
一、前期准备
1.1 创建工程
创建springboot项目,springboot版本为2.5.0,引入spring-boot-starter-web依赖,pom文件如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.5.0</version><relativePath/> <!-- lookup parent from repository --></parent><groupId>com.example</groupId><artifactId>springboot</artifactId><version>0.0.1-SNAPSHOT</version><name>springboot</name><description>Demo project for Spring Boot</description><properties><java.version>1.8</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency></dependencies><build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId></plugin></plugins></build></project>
1.2 创建文件
🔶 创建一个简单的Controller用于测试
com/springboot/controller/HelloController
@RestController
public class HelloController {public void helloController() {System.out.println("创建了");}@RequestMapping("hello")public String hello() {return "hello";}
}
🔶 创建一个配置类,用于扫描com包下的文件
com/test1/config/Config
@Configuration
@ComponentScan("com")
public class Config {
}
🔶 创建一个简单的Service用于测试
com/test1/service/UserService
@Component
public class UserService {
}
🔶 修改启动类
@Import(Config.class)
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);System.out.println(run.getBean(UserService.class));}}
从ConfigurableApplicationContext
的名字可以看出来,它是一个容器(ApplicationContext),所以我们可以通过这个容器来获取bean对象,这里就获取刚刚创建的UserService。
1.3 说明
为了使用@Import注解的方式加载配置类,项目结构设置如下。
可以看出service和config并不在启动类的同级目录下。这就说明启动类并不会去自动加载它们。所以,我们需要想办法让启动类加载UserService。
首先,可以通过@Import(Config.class)
注解让启动类加载Config配置类。
如果Config配置类放到启动类同级目录下就不需要Import注解了,因为会自动扫描加载。
在Config配置类中,通过@ComponentScan("com")
注解,让容器加载整个com包下的bean对象,而不是仅仅加载启动类同级目录下的bean对象。
所以,@Import注解在这里的作用是:引入其他的配置类。
如果我们把所有的配置都写在一个配置类中不便于我们进行管理。所以Spring也支持我们编写多个配置类,只要使用@Import注解引入其他配置类即可。作用相当于
<import>
标签。
@Import注解还有其他两个作用,在分析源码的过程中就可以看到了:
- 引入ImportSelector
- 引入ImportBeanDefinitionRegistrar
1.4 总结
@Import注解具有以下作用,下面将分为三部分介绍:
- 引入其他的配置类
- 引入ImportSelector
- 引入ImportBeanDefinitionRegistrar
二、引入配置类过程探究
2.1 配置类的解析
前面在探究默认组件扫描的时候发现配置类的解析主要在类ConfigurationClassParser
的doProcessConfigurationClass
方法中完成。
通过注释我们可以看出它可以解析@PropertySource 、@ComponentScan 、@Import 、@ImportResource 、@Bean等注解。
// Process any @PropertySource annotations
...
// Process any @ComponentScan annotations
...
// Process any @Import annotations
...
// Process any @ImportResource annotations
...
// Process individual @Bean methods
...
解析@Import是这行代码:
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
那么下面我们就来看看这个方法。
2.2 getImports(sourceClass)
🔶 processImports()
方法
通过断点调试执行到这条代码。
第一次运行到此,可以看到sourceCLass是我们自定义的HelloController。这个HelloController里面并没有我们想要的Import注解。
第二次运行到此,可以 看到sourceClass是我们的启动类,里面有Import注解。
processImports()
方法传入了很多变量,其中有一个getImports(sourceClass)
方法,意思大概是获取Import注解的字节码,所以在之前应先看看getImports(sourceClass)
。
🔶 getImports(sourceClass)
方法
imports
:存放导入进来的SourceClass
visited
:记录已经处理过的SourceClass
🔶 collectImports()
方法
收集所有带有@Import注解的类。
visited.add(sourceClass)
:第一次添加一定会成功,返回true;如果重复添加返回false。递归调用时防止重复调用、重复添加。
sourceClass.getAnnotations()
:获取类上面的所有注解,返回注解集合。
可以看到这里获取了两个注解@Import、@SpringBootApplication。@SpringBootApplication这个注解会递归调用,因为要看看这个注解上面是否包含@Import注解。
imports.addAll(sourceClass.getAnnotationAttributes(Import.class.getName(), "value"));
这段代码获取了配置类的字节码对象,把它放到imports集合里面。
所有使用了@Import注解的类都会添加到这个集合里面。
🔷 所以,这个getImports
方法最后就获取到了所有带有@Import注解的字节码对象。
2.3 processImports()
先经过判断集合是否为空,校验等操作。
开始遍历集合:
前两个元素不看,只看我们自定义的Config。
candidate.isAssignable(xxx.class)
:判断是不是xxx的子类或实现类
Config既不是ImportSelector实现类,也不是ImportBeanDefinitionRegistrar的实现类,所以它会运行到这里:
else {// Candidate class not an ImportSelector or ImportBeanDefinitionRegistrar ->// process it as an @Configuration classthis.importStack.registerImport(currentSourceClass.getMetadata(), candidate.getMetadata().getClassName());processConfigurationClass(candidate.asConfigClass(configClass), exclusionFilter);
}
后面将要介绍如何处理配置类,在【3.2.4】中介绍。
2.4 结论
Configuration的doProcessConfigurationClass方法在处理启动类的时候会递归扫描其上所有的@Import注解,获取其中的value属性值添加到集合中。
然后获取遍历这个集合判断他们是ImportSelector的子类还是ImportBeanDefinitionRegistrar的子类还是加了@Configuration的配置类。如果前面两种情况都不满足就说明它是配置类,会继续调用processConfigurationClass方法来解析这个导入进来的配置类。
ImportSelector、ImportBeanDefinitionRegistrar两种情况在后面介绍。
三、ImportSelector探究
当有很多配置类的时,如果使用@Import注解来导入配置类是十分麻烦的。这时可以使用ImportSelector,它可以根据字符串数组(数组元素为类的全类名)来批量的加载指定的bean。
3.1 修改项目
项目结构如下:
🔶 com/test/importselector/MySelector.java
创建MySelector类实现ImportSelector 接口。
通过selectImports()
方法加载配置文件,读取需要加载的全类名,并封装为字符串数组返回。
通过getExclusionFilter()
方法排除一些不要加载的类(它是default方法,非必要可以不实现)。Predicate<T>
是函数式接口,可以通过lambda表达式实现boolean test(T t)
方法,输入s字符串并判断条件返回true或false。
这里的条件是:如果字符串内包含Admin则返回true,也就是说传入com.test.service.AdminService
全类名时返回true,那么将不会加载AdminService。
public class MySelector implements ImportSelector {@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {// 读取配置文件中的数据ResourceBundle rb = ResourceBundle.getBundle("import");String classNames = rb.getString("className");// 转换成一个字符串数组返回return classNames.split(",");}/*** 排除过滤器* selectImports方法返回的字符串数组中的字符串会传递到test方法里面* 如果输入的字符串后返回true,那么就不会加载。* 输入的字符串后返回false,才会加载。*/@Overridepublic Predicate<String> getExclusionFilter() {// 使用lambda表达式,如果包含Admin字符串则返回true,那么就不会加载return s -> s.contains("Admin");}
}
🔶 com/test/service/xxxService.java
@Component
public class AdminService {
}
@Component
public class GroupService {
}
@Component
public class UserService {
}
🔶 src/main/resources/import.properties
配置文件,在MySelector 加载这个配置文件。
className=com.test.service.AdminService,\com.test.service.GroupService
\
表示换行
🔶 com/springboot/SpringbootApplication.java
@Import(MySelector.class)
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);System.out.println(run.getBean(GroupService.class));System.out.println(run.getBean(AdminService.class));}}
3.2 探究源码
3.2.1 回顾配置类解析
前面已经介绍过了,配置类的解析主要在类ConfigurationClassParser
的doProcessConfigurationClass
方法中完成。
解析@Import
是这行代码:
// Process any @Import annotations
processImports(configClass, sourceClass, getImports(sourceClass), filter, true);
getImports
方法获取到了所有带有@Import注解的字节码对象。
在processImports()
处理过程中有个判断,判断Config是ImportSelector
实现类,还是ImportBeanDefinitionRegistrar
的实现类,如果都不是的话则是普通的配置类。
3.2.2 processImports()
在找自定义的ImportSelector时候,先看到了Springboot本身包含的ImportSelector:
org.springframework.boot.autoconfigure.AutoConfigurationImportSelector
不过暂时先不看它,跳过这个后,看到了我们自定义的
com.test.importselector.MySelector
下面来看看如果是ImportSelector的实现类,具体会做些什么
if (candidate.isAssignable(ImportSelector.class)) {// Candidate class is an ImportSelector -> delegate to it to determine imports// 加载类获得字节码对象Class<?> candidateClass = candidate.loadClass();// 获得ImportSelector对象,就是MySelecor的对象ImportSelector selector = ParserStrategyUtils.instantiateClass(candidateClass, ImportSelector.class,this.environment, this.resourceLoader, this.registry);// 过滤器,我们在MySelector里面实现了getExclusionFilter方法Predicate<String> selectorFilter = selector.getExclusionFilter();// 如果我们没实现getExclusionFilter方法,这里就是nullif (selectorFilter != null) {// 如果实现了getExclusionFilter方法,就会把实现的判断条件加进去exclusionFilter = exclusionFilter.or(selectorFilter);}// 判断是不是DeferredImportSelector实现类,这里是falseif (selector instanceof DeferredImportSelector) {this.deferredImportSelectorHandler.handle(configClass, (DeferredImportSelector) selector);}// 不是DeferredImportSelector的实现类,只剩下ImportSelector的实现类else {// 获取全类名字符串数组,其中包含com.test.service.AdminService和com.test.service.GroupServiceString[] importClassNames = selector.selectImports(currentSourceClass.getMetadata());// 根据importClassNames的全类名和exclusionFilter过滤条件加载对象,封装为SourceClass对象存储在集合当中Collection<SourceClass> importSourceClasses = asSourceClasses(importClassNames, exclusionFilter);// 递归调用processImports方法,因为有可能被加载的类中还有注解processImports(configClass, currentSourceClass, importSourceClasses, exclusionFilter, false);}
}
下面分别看看asSourceClasses()
方法和processImports()
方法。
3.2.3 asSourceClasses()
下面再看看asSourceClasses()
方法
private Collection<SourceClass> asSourceClasses(String[] classNames, Predicate<String> filter) throws IOException {// classNames 为字符串数组包含com.test.service.AdminService和com.test.service.GroupService两个字符串// filter为我们自定义getExclusionFilter()过滤器,当含有Admin字符串时返回trueList<SourceClass> annotatedClasses = new ArrayList<>(classNames.length);// 遍历字符串数组for (String className : classNames) {// 通过asSourceClass()方法处理,并添加到annotatedClasses集合中,这个集合中存储SourceClass对象。annotatedClasses.add(asSourceClass(className, filter));}return annotatedClasses;
}
下面再看看asSourceClass()
方法
// 该方法一定会返回一个SourceClass 对象
SourceClass asSourceClass(@Nullable String className, Predicate<String> filter) throws IOException {// 如果className为null或者filter条件成立(这里的条件就是MySelector类中getExclusionFilter方法中我们自定义的方法)// 如果成立就会返回this.objectSourceClass,就是一个普通的Object对象,因为该方法需要一个返回值,所以不能返回null。if (className == null || filter.test(className)) {return this.objectSourceClass;}if (className.startsWith("java")) {// Never use ASM for core java typestry {return new SourceClass(ClassUtils.forName(className, this.resourceLoader.getClassLoader()));}catch (ClassNotFoundException ex) {throw new NestedIOException("Failed to load class [" + className + "]", ex);}}// 如果条件不成立,就把它封装成SourceClass对象并返回return new SourceClass(this.metadataReaderFactory.getMetadataReader(className));
}
我们可以看到importClassNames字符串数组中包含:
我们可以看到importSourceClasses集合中包含:
其中AdminService被过滤掉了,过滤后只能返回Object的SourceClass对象;而GroupService的SourceClass对象正常加载。
最后再将importSourceClasses传入processImports()方法中递归调用,此时前两个条件不符合,只能当作@Configuration类来进行处理。
那么下面看看如何处理配置类。
3.2.4 processConfigurationClass()
protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {...// Recursively process the configuration class and its superclass hierarchy.SourceClass sourceClass = asSourceClass(configClass, filter);do {sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);}while (sourceClass != null);// 关键点:添加到配置类集合configurationClasses当中// 后面将要对这个配置类集合进行处理this.configurationClasses.put(configClass, configClass);
}
继续往下看如何处理configurationClasses
。
3.2.5 processConfigBeanDefinitions()
在ConfigurationClassPostProcessor类的processConfigBeanDefinitions()
方法中。
可以看到这个哈希表中存储了很多配置类
configClasses是将configurationClasses转换成了LinkedHashSet。
后面通过loadBeanDefinitions方法加载成BeanDefinition对象。可以参考BeanDefinition的创建过程
this.reader.loadBeanDefinitions(configClasses);
后面可以通过BeanDefinition创建Bean对象。可以参考Bean对象的创建
3.3 总结
Configuration的doProcessConfigurationClass方法在处理启动类的时候会递归扫描其上所有的@Import注解,获取其中的value属性值添加到集合中。
然后获取遍历这个集合判断他们是ImportSelector的子类还是ImportBeanDefinitionRegistrar的子类还是加了@Configuration的配置类。
如果是ImportSelector则会通过反射创建其对象,调用方法获取字符串数组,封装成SourceClass对象。然后递归调用这些处理import的方法,对这些期望导入的类做同样的处理。
如果导入的不是ImportSelector或者ImportBeanDefinitionRegistrar,会被当成配置类调用processConfigurationClass进行处理。这个方法会把他们添加到一个配置类的哈希表中(configurationClasses)。后面会把配置类集合加载成BeanDefinition对象。
四、ImportBeanDefinitionRegistrar探究
应用场景:如果要实现动态Bean的装载可以使用ImportBeanDefinitionRegistrar。尤其是想要装载动态代理对象的时候。例如Mybatis的启动器就是使用了它实现了Mapper接口的代理对象装载的。
4.1 低级用法
通过Registrar往容器中注入Dog对象。
创建beanDefinition并设置BeanClassName(“com.test.registrar.Dog”),最后注册的bean工厂registry中。
public class SimpleRegistrar implements ImportBeanDefinitionRegistrar {/*** 注册beanDefinition* spring容器可以通过beanDefinition创建bean对象* @param importingClassMetadata 加了@Import(SimpleRegistrar.class)注解的类的一些信息,如类名、字节码对象* @param registry bean工厂,beanDefinition就是要注册到bean工厂*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 创建一个Dog对应的BeanDefinition对象// 创建BeanDefinition实现类对象GenericBeanDefinition beanDefinition = new GenericBeanDefinition();beanDefinition.setBeanClassName("com.test.registrar.Dog");// 把BeanDefinition对象进行注册registry.registerBeanDefinition("dog", beanDefinition);}
}
启动类,需要加上注解@Import(SimpleRegistrar.class)
@Import(SimpleRegistrar.class)
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);}}
其实上面这种注册Bean的方法等价于用配置文件注册
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean class="com.test.registrar.Dog" id="dog"></bean>
</beans>
这只是简单的是练习,当有很多Bean对象的时候并不适用。
4.2 中级用法
想要去识别加了指定注解的类,并把这些类的BeanDefinition对象注册到容器中,这时候就可以使用ClasPathBeanDefinitionScanner。
项目目录如下:
🔶 自定义注解
参考@Component注解的写法,后面我们将自动加载带有这个注解的类。
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponent {
}
🔶 ComponentRegistrar
自定装载com.test.registrar包下面带有com.test.registrar.MyComponent注解的类。
public class MyComponentRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 创建Scanner对象// 使用默认过滤器:true,类上面加上了默认注解才能转换成beanDefinition// 这里不使用默认过滤器,我们要自定义过滤器ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry, false);// 添加过滤器,在scanner.scan扫描后会把这个类的字节码对象传入到这个过滤器的match方法进行判断scanner.addIncludeFilter(new TypeFilter() {/*** @param metadataReader 这个类的相关信息* @param metadataReaderFactory* @return false 被过滤掉 true 不会被过滤* @throws IOException*/@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {// 如果这个类加了@MyComponent注解就添加到容器中return metadataReader.getAnnotationMetadata().hasAnnotation("com.test.registrar.MyComponent");}});// 进行扫描scanner.scan("com.test.registrar");// 测试有没有注册BeanDefinition}
}
🔶 Dog
带有@MyComponent注解
@MyComponent
public class Dog {
}
🔶 启动类
要通过Import注解导入MyComponentRegistrar
@Import(MyComponentRegistrar.class)
@SpringBootApplication
public class SpringbootApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(SpringbootApplication.class, args);}}
4.3 高级用法
FactoryBean:一些对象的创建过程比较复杂,可以使用FactoryBean来实现对象的创建。可以让Spring容器需要创建该对象的时候调用factoryBean来实现创建。尤其是一些动态代理对象的创建。
可以参考FactoryBean创建对象。
🔶 案例目标:
实现类似Mybatis的效果,定义接口,接口上使用指定注解进行标识。然后能生成对应的动态代理对象装载到容器中。
🔶 自定义注解
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyMapper {
}
🔶 给对应接口加上注解
@MyMapper
public interface MyUserMapper {void select();
}
🔶 创建MyMapperScanner继承ClassPathBeanDefinitionScanner
需要重写isCandidateComponent方法,保证接口能够被加载。因为ClassPathBeanDefinitionScanner的isCandidateComponent方法不会加载接口。
public class MyMapperScanner extends ClassPathBeanDefinitionScanner {public MyMapperScanner(BeanDefinitionRegistry registry) {super(registry);}public MyMapperScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {super(registry, useDefaultFilters);}@Overrideprotected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {AnnotationMetadata metadata = beanDefinition.getMetadata();// 是接口的话,返回truereturn metadata.isInterface();}
}
🔶 创建MapperFactoryBean 实现FactoryBean 接口
通过动态代理创建接口的实现类对象并返回代理对象。
public class MapperFactoryBean implements FactoryBean {/*** 用于保存接口的全类名*/private String className;public MapperFactoryBean(String className) {this.className = className;}@Overridepublic Object getObject() throws Exception {Class<?> interfaceClass = Class.forName(className);// 生成动态代理对象返回Object proxyInstance = Proxy.newProxyInstance(MapperFactoryBean.class.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {@Overridepublic Object invoke(Object o, Method method, Object[] objects) throws Throwable {// 获取当前方法名System.out.println(method.getName());if ("select".equals((method.getName()))) {System.out.println(className + "动态代理对象的select方法被执行了!!");}return null;}});return proxyInstance;}@Overridepublic Class<?> getObjectType() {try {Class<?> interfaceCLass = Class.forName(className);return interfaceCLass;} catch (ClassNotFoundException e) {e.printStackTrace();}return null;}
}
🔶 创建MyMapperRegistrar实现ImportBeanDefinitionRegistrar接口
public class MyMapperRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 创建扫描器// 使用默认过滤器:true,类上面加上了默认注解才能转换成beanDefinitionMyMapperScanner scanner = new MyMapperScanner(registry, false);// 设置一个Include过滤器,判断是否有MyMapper注解scanner.addIncludeFilter(new TypeFilter() {/*** @param metadataReader 这个类的相关信息* @param metadataReaderFactory* @return false 被过滤掉,true 不会被过滤* @throws IOException*/@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {return metadataReader.getAnnotationMetadata().hasAnnotation(MyMapper.class.getName());}});// 进行扫描Set<BeanDefinition> beanDefinitions = scanner.findCandidateComponents("com.test.registrar");// 扫描到BeanDefinition后进行转换 使用MapperFactoryBean的BeanDefinition进行注册for (BeanDefinition beanDefinition : beanDefinitions) {AbstractBeanDefinition factoryBeanDefinition = BeanDefinitionBuilder.genericBeanDefinition(MapperFactoryBean.class).addConstructorArgValue(beanDefinition.getBeanClassName()).getBeanDefinition();registry.registerBeanDefinition(beanDefinition.getBeanClassName(), factoryBeanDefinition);}}
}