nativeimage GraalVM是从main方法开始分析,所有可达的类和方法会被记录。 但是反射、动态代理、资源文件等无法通过简单的静态分析捕获,为了支持这部分代码的行为,GraalVM支持配置文件来支持JIT时常用的做法。 GraalVM推荐在METAINFnativeimage(或子文件夹,如为避免不同jar下的配置冲突,放在METAINFnativeimage{groupId}{artifactId})下的nativeimage。properties来形成构建本地代码所需要的命令行参数。nativeimages。properties一般包含哪些类可以在构建时初始化(initializeatbuildtime),哪些只能运行时初始化(initializeatruntime)。 有被JDK动态代理的接口,可以记录到proxyconfig。json,比如MyBatis的SqlSession,Spring的Component等注解。 有JNI调用的类,可以记录到jniconfig。json,比如sun。instrument。InstrumentationImpl。 有要被反射调用的,可以记录到reflectconfig。json,比如我们的Mapper要被MyBatis代理,要求Mapper接口的方法可以被反射查询到,参数和返回要被反射调用gettersetter来取值设置值。 有资源文件,可以记录到resourceconfig。json,比如messages。properties这种国际化资源、application。proeprties这种应用配置以及MyBatis的Mapper文件等等。 还有序列化相关的,可以记录到serializationconfig。json。 这些配置文件可以通过GraalVM提供的nativeimageagent来自动生成绝大部分内容:agentlib:nativeimageagentconfigoutputdirpathfile 然而,nativeimage。properties却不会自动生成,需要我们手动添加。如果不想使用默认的配置文件名,可以在修改文件名后(比如proxyconfig。json改成proxy。json,甚至放在子文件夹下),使用参数告知graalvm。nativeimage。properties示例如下:Argsallowincompleteclasspathinitializeatbuildtimeorg。slf4j。Logger,org。slf4j。LoggerFactory,org。slf4j。MDCJaddexportsjava。managementsun。managementALLUNNAMEDH:DynamicProxyConfigurationResources{。}proxy。jsonH:ReflectionConfigurationResources{。}reflect。jsonH:ResourceConfigurationResources{。}resource。jsonDsys。propspringnative 那么springnative给我们带来了哪些便利呢? springnative提供了诸多注解,帮助我们生成GraalVM所规范的配置。 比如InitializationHint注解可以生成nativeimage。properties里的initializeatbuildtime、initializeatruntime。 比如JdkProxyHint注解可以生成proxyconfig。json的内容。 比如ResourceHint注解可以生成resourceconfig。json内容。 比如SerializationHint注解生成serializationconfig。json需要的序列化反序列化内容。 比如TypeHint注解(明细配置可结合FieldHint和MethodHint)生成reflectconfig。json需要的哪些字段方法可被反射调用。 介绍过开胃菜,接下来就是正式的大餐:IoC和AOP。 我们知道spring提供了xml、java代码、java注解等多种配置方式,帮助我们生成bean对象、查找并注入依赖、增强bean。而springboot提供了自动配置,开启约定大于配置,让我们无需在每次新建系统时重复配置。 springnative针对这些功能,结合GraalVM的特点,为我们生成代码,来接好springspringboot的岗位。springnative会自动为每个存在依赖注入的包生成ContextBootstrapInitializer类,为每个类生成register前缀与类名组合的方法。方法内容大致可表示如下:publicfinalclassContextBootstrapInitializer{publicstaticvoidregister{klazz。simpleName}(DefaultListableBeanFactorybeanFactory){BeanDefinitionRegistrar。of({beanName},{klazz。simpleName}。class)。instanceSupplier((instanceContext){{klazz。simpleName}beannew{klazz。simpleName}();instanceContext。field({field。name},{field。class。simpleName}。class)。invoke(beanFactory,(attributes){Field{field。name}FieldReflectionUtils。findField({klazz。simpleName}。class,{field。name},{field。class。simpleName}。class);ReflectionUtils。makeAccessible({field。name}Field);ReflectionUtils。setField({field。name}Field,bean,attributes。get(0));});})}} 对于springboot的autoconfiguration,在满足条件时,同样生成ContextBootstrapInitializer。对于各个jar包下的spring。factories文件,在org。springframework。aot下生成StaticSpringFactories,将类型和生成对象方式保存,以供后续使用。 在org。springframework。aot包下还生成了ContextBootstrapInitializer,与应用定义bean的不同之处在于,此类实现了ApplicationContextInitializer。 在SpringApplication构造时,通过生成的SpringFactoriesLoader加载类型及对应的对象(非AOT模式为加载spring。factories,AOT模式为StaticSpringFactories),引起初始化,大致代码如下:publicclassContextBootstrapInitializerimplementsApplicationContextInitializerGenericApplicationContext{privateImportAwareBeanPostProcessorcreateImportAwareBeanPostProcessor(){MapString,StringmappingsnewLinkedHashMap();mappings。put(org。springframework。transaction。annotation。ProxyTransactionManagementConfiguration,ml。iamwhatiam。baostock。Application);mappings。put(org。springframework。cache。annotation。ProxyCachingConfiguration,ml。iamwhatiam。baostock。Application);returnnewImportAwareBeanPostProcessor(mappings);}Overridepublicvoidinitialize(GenericApplicationContextcontext){infrastructureDefaultListableBeanFactorybeanFactorycontext。getDefaultListableBeanFactory();beanFactory。setAutowireCandidateResolver(newContextAnnotationAutowireCandidateResolver());beanFactory。addBeanPostProcessor(createImportAwareBeanPostProcessor());BeanDefinitionRegistrar。of({mainClass。name},{mainClass。simpleName}。class)。instanceSupplier({mainClass。simpleName}::new)。register(beanFactory);{groupId}。{artifactId}。ContextBootstrapInitializer。register{klazz。simpleName}(beanFactory);BeanDefinitionRegistrar。of(org。springframework。boot。context。properties。ConfigurationPropertiesBindingPostProcessor,ConfigurationPropertiesBindingPostProcessor。class)。instanceSupplier(ConfigurationPropertiesBindingPostProcessor::new)。customize((bd)bd。setRole(2))。register(beanFactory);otherEnableAutoConfigurationbeanorg。springframework。boot。autoconfigure。cache。ContextBootstrapInitializer。registerSimpleCacheConfiguration(beanFactory);}} 当然,并非所有的自动配置类其类型都是公开的(classXXAutoconfiguration,而不是publicclassXXAutoConfiguration),对于这种情况,springnative为他们在同包名下生成FactoryProvider类,该静态方法名为类型名,返回该类型。 还有些bean的类型,其构造函数是私有的,springnative为其生成内部类来创建实例。 至此,当springboot的SpringApplication运行时,创建完DefaultBootstrapContext便由org。springframework。aot下的ContextBootstrapInitializer进行初始化,此时便会将各种bean及其生成方式注册到spring的上下文。