如何自定义classloader_关于jar动态加载

如何自定义classloader,关于jar动态加载?

您可以使用URLClassLoader动态加载指定路径的jar文件,然后以loadClass("类名")的方式载入具体Class。获得Class对象后,就可以按照标准的Java反射方式进行操作了。相关API的详细调用方式,您可以阅读javadoc,或者直接搜索相关方法名,就会看到不少的示例。这里篇幅有限,不方便赘述

jar包里面的代码如何读取jar包中的配置文件?

您好,读取jar包内配置文件:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("/configfilename.properties");

读取jar包外配置文件:

String filePath = System.getProperty("user.dir") + "/conf/configfilename.properties";

InputStream in = new BufferedInputStream(new FileInputStream(filePath));

另外,如果app中使用到log4j.properties文件,默认的存放路径是src/log4j.properties,同上面一样,我想把log4j.properties放在其他目录中,这样一来,在修改log4j配置文件的时候无需重新打jar包。

在main函数第一行添加如下代码:

PropertyConfigurator.configure(System.getProperty("user.dir") + "/conf/log4j.properties");

我的世界modloader怎么解压?

MODloader是加载MOD使用的,为了防止MOD与MOD之间的冲突(一般可以解决大部分的mod冲突问题)。下载modloader后,安装需要解压,并找到minecraft客户端/.minecraft/bin目录中的minecraft.jar文件并用rar的方式打开,删除META-INF文件夹,然后将解压的class文件和其他文件拖入其中。 注意有些mod需要forge不兼容modloader(看好你的minecraft版本,去下载对应版本的mod)。 每个mod有不同的安装法,一般就把文件拉入bin里就好了(小部分mod可能安装方法比较特别,但是下载的地方都会有说明)。

APP中嵌入APP可以吗?

看了很多答案,都说是嵌入的小程序,其实支付宝之前的版本里面嵌入的就是饿了吗APP,APP中嵌入APP是可以的,下面具体说说实现原理。

使用插件化技术实现APP嵌入APP

安卓系统加载APP的原理

安卓开发语言是JAVA,当然现在有kotlin了,这里我就拿java来说吧。

我们开发编写的java文件会被编译成class文件,然后才能被java虚拟机加载解析并运行。

那安卓使用的是Dalvik虚拟机,它可执行不了class文件,所以安卓编译器会把java文件编译成dex文件,才能被Dalvik虚拟机是加载解析运行。

那Dalvik虚拟机时候如何加载dex文件的呢?

Android支持动态加载的两种方式是:DexClassLoader和PathClassLoader。DexClassLoader可加载jar/apk/dex,且支持从SD卡加载;

PathClassLoader只能加载已经安装在Android系统内APK文件。

PathClassLoader 的限制要更多一些,它只能加载已经安装到 Android 系统中的 apk 文件,也就是 /data/app 目录下的 apk 文件。其它位置的文件加载的时候都会出现 ClassNotFoundException。

了解了基本的加载方法之后,就可以安卓这套方法,实现加载逻辑,达到运行apk的目的。

实现加载逻辑

加载逻辑需要宿主APP去实现的,然后提供使用文档给插件方调用。

如何实现加载逻辑,简单来说就是根据系统的逻辑负责一套就ok了。

安卓包下面有asset资源、raw资源、图片资源、xml文件、dex文件等等。

这些资源和文件的加载都需要写一套加载逻辑,大致和系统的相同。

宿主app可以使用系统的加载方法,而插件方只能使用宿主提供的加载方法,否则会报错崩溃。

插件化的两个加载方式

1.随宿主APP一起打包成apk,系统会将插件当成文件进行编译。这种方式比较少,首先这种内嵌的方式,完全可以用模块化代替,其次是不支持动态更新。

2.提供下载地址给宿主app,需要用到插件时直接下载到SD卡,然后进行加载解析。这种支持动态化更新,也就是只要提供个接口给宿主app,如果接口返回需要更新,那这个时候在重新下载插件。

基本上都偏向于第二种加载方式。

插件化方式的好处

1.减少app包体积

2.便于分工管理,解耦

3.动态更新,减少发版

...

总结

APP嵌入APP是可以通过插件化来实现的,并且在大型项目插件化实用非常频繁,不只是加载app,还可以是其他的文件、资源等等。

上面简单介绍安卓插件化的原理,如有说的不好或不对的地方,还请大佬指教!

我是非著名攻城狮,希望我的回答对您有用,感谢您的关注与支持!

starter如何设置自动配置注解?

在了解如何设置自动配置注解之前可以先看看spring-boot的自动配置原理,了解了原理之后,在来看如何配置就很简单了;

SpringBoot自动配置

1.自动配置注解

要想使用自动配置功能,SpringBoot提供了注解@EnableAutoConfiguration,当然不需要我们配置因为在@SpringBootApplication注解中默认以及启用了;

可以看到@SpringBootApplication注解本身也有注解@EnableAutoConfiguration:

在注解@EnableAutoConfiguration中重点看一下@Import注解中使用的AutoConfigurationImportSelector类,此类是自动注解的核心类,会有条件的加载我们默认指定的配置类;这里有两个概念一个是有条件,一个是配置类,分别简单介绍一下:配置类可以简单理解就是相关组件对接SpringBoot的对接类,此类可以做一些初始化的工作;有条件表示并不是有配置类就能被对接上,是有条件的,SpringBoot默认提供了大量配置类,但并不是所有配置类都能被加载初始化的,是有条件的,比如mybatis在没有数据源的情况下,没有mybatis基础包的情况下是不能被对接的;下面首先看一下SpringBoot提供的哪些条件类;

2.条件类

SpringBoot提供了很多条件类,可以在配置中上配置注解条件类,相关条件类可以在spring-boot-autoconfigure包下的org.springframework.boot.autoconfigure.condition下找到,主要包含如下:

ConditionalOnBean:当前容器有指定Bean的条件下;ConditionalOnClass:当前类路径下有指定类的条件下;ConditionalOnCloudPlatform:当指定了云平台的时候;ConditionalOnExpression:SpEL表达式作为判断条件;ConditionalOnJava:JVM版本作为判断条件;ConditionalOnJndi:在JNDI存在的条件下查找指定的位置;ConditionalOnMissingBean:当容器里没有指定Bean的情况下;ConditionalOnMissingClass:当类路径下没有指定的类的条件下;ConditionalOnNotWebApplication:当前项目不是WEB项目的条件下;ConditionalOnProperty:当前应用是否配置了指定属性指定的值;ConditionalOnResource:只有当指定的资源位于类路径下;ConditionalOnSingleCandidate:bean工厂中只有一个或者有多个情况下是主要的候选bean;ConditionalOnWebApplication:当前项目是WEB项目的条件下。

以上是注解类,注解本身没有功能,只是提供标记的功能,具体功能在@Conditional中指定的,比如ConditionalOnBean注解如下所示:

相关功能的实现就在OnBeanCondition类中,同样其他注解类的实现类也在包org.springframework.boot.autoconfigure.condition下找到;

3.自动配置过程

Springboot应用启动过程中使用ConfigurationClassParser分析配置类,此类中有一个processImports方法,此方法用来处理@Import注解,在@EnableAutoConfiguration注解存在@Import注解,这时候会实例化注解中的AutoConfigurationImportSelector,在其内部有一个AutoConfigurationGroup内部类,内部类有两个核心方法分别是:process和selectImports;

此方法主要获取经过条件过滤之后可用的自动配置类,主要调用AutoConfigurationImportSelector中的getAutoConfigurationEntry完成的:

首先获取了所有备选的自动配置类,然后删除了重复和被排除的类,最后通过条件进行筛选出可用的配置类,下面分别看一下,首先看一下如何获取所有备选的配置类:

通过SpringFactoriesLoader获取类路径下META-INF/spring.factories文件中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的配置类,可以看一下spring-boot-autoconfigure.jar中的spring.factories内容:

当然这里只是截取了其中一个类路径jar下的部分配置,获取所有配置类之后进行去重,去被排除的类,然后进行条件过滤,下面重点看一下:

此方法大致就是首先获取配置的AutoConfigurationImportFilter ,然后对之前获取的所有配置类进行过滤,最后返回过滤之后的配置类;AutoConfigurationImportFilter同样也是通过SpringFactoriesLoader类进行加载类路径下META-INF/spring.factories,只不过当前的key是:org.springframework.boot.autoconfigure.AutoConfigurationImportFilter,可以看一下SpringBoot默认配置的filter:

可以看到Filter其实就是上文介绍的条件类,这里默认了OnBeanCondition,OnClassCondition以及OnWebApplicationCondition,已这里使用的Mybatis为例看一下MybatisAutoConfiguration的注解:

可以看到其中有用到@ConditionalOnClass,表示必须提供SqlSessionFactory和SqlSessionFactoryBean类的情况下才加载此配置类,而整两个是正式Mybatis基础包中提供的;有了基础包还不行,还需要DataSource,而且DataSource必须在MybatisAutoConfiguration实例化之前初始化好,SpringBoot是如何实现,继续看另外一个核心方法selectImports():

首先是对被排除类的一个过滤,然后接下来重点看一下对配置类进行排序的一个方法,具体操作在类AutoConfigurationSorter中进行的,具体方法为getInPriorityOrder():

首先使用order进行排序,然后使用@AutoConfigureBefore和@AutoConfigureAfter就行排序;order其实就是通过注解@AutoConfigureOrder进行排序的,值是一个整数,结构类似如下:

@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE + 10)

@AutoConfigureBefore和@AutoConfigureAfter字面意思也很好理解,指定在其他配置类之前和之后,所以可以看到在MybatisAutoConfiguration中有如下配置:

表示在DataSourceAutoConfiguration配置类加载之后才会加载Mybatis配置类,这样就解决了依赖关系;还有上文提到的Mybatis操作数据库依赖的SqlSessionFactory和SqlSession,都在MybatisAutoConfiguration进行了初始化操作;SpringBoot本身其实以及提供了大量常用组件的自动配置类,我们只需要提供满足的特定条件,SpringBoot自动会帮我加载初始化等操作;

下面用一个简单的实例来看看如何自定义一个自动配置类;

自定义配置类

接下来我们用很简单的实例来看一下自定义的流程,一个格式化大写消息的实例;

1.pom文件引入依赖

Spring 官方 Starter通常命名为spring-boot-starter-{name}如 spring-boot-starter-web,Spring官方建议非官方Starter命名应遵循{name}-spring-boot-starter的格式;

2.服务类和属性配置类

属性类提供了type参数可以在application.properties中配置,可配置值包括:upper,lower;

3.自动配置类和创建spring.factories文件

这个就是自定义的自动配置类,SpringBoot启动的时候会根据条件自动初始化;最后在resources/META-INF/下创建spring.factories文件:

4.测试

在其他SpringBoot中可以引入上面创建的项目,引入方式也很简单:

同时在application.properties配置格式化类型:

启动应用,浏览器访问http://localhost:8888/format?word=hello,结果为:HELLO

以上分析了一下springboot的自动配置原理,并自定义一个自动配置类,并且运行,相信对你有所帮助;

更多可以参考本人之前的文章:https://www.toutiao.com/i6749752249532023309/

给TA打赏
共{{data.count}}人
人已打赏
0 条回复 A文章作者M管理员
    暂无讨论,说说你的看法吧