1. 前言
- SpringFactoriesLoader类的主要作用是通过类路径下的META-INF/spring.factories文件获取工厂类接口的实现类,初始化并保存在缓存中,以供Springboot启动过程中各个阶段的调用。
- SpringFactoriesLoader.loadFactories():是根据参数factoryClass获取spring.factories下配置的所有实现类实例,返回
List<T>
的。 - SpringFactoriesLoader.loadFactoryNames():是根据参数factoryClass获取spring.factories下配置的所有实现类的全限定类名,
返回List<String>
的。
2. 基本使用
-
先准备如下内容(3个类,以及resource目录下的META-INF/spring.factories文件):
public interface IUserService { } public class UserService implements IUserService { } public class UserService2 implements IUserService { }
com.example.csdn.spring_factory_test.IUserService=\ com.example.csdn.spring_factory_test.UserService,\ com.example.csdn.spring_factory_test.UserService2
-
demo代码:
public class demo { public static void main(String[] args) { // 参数null的位置,实际上是传递类加载器,这里传null,是因为SpringFactoriesLoader源码里面会有判断 // 如果判断为null,默认拿自己类的类加载器,因此我懒得传了 // 这里是解析出 spring.factories的实现类的全类限定路径 // 有的人就问,直接创建对象出来不好吗,为什么要获取类限定路径呢? // 肯定是想拿到字节码文件做一些判断啦,比如有没有某些注解乱七八糟的 List<String> list = SpringFactoriesLoader.loadFactoryNames(IUserService.class, null); System.out.println(list); // 这里就是直接创建对象了 List<IUserService> userServices = SpringFactoriesLoader.loadFactories(IUserService.class, null); System.out.println(userServices); } }
3. 结合EnableAutoConfiguration的使用
-
先思考一下,spring要提供这个springfactories的功能肯定有原因的。
-
如上面基本用法,SpringFactoriesLoader.loadFactories()方法可以直接创建类对象。
-
对象哦,又是spring,这不得马上上到@Bean注解的作用,创建一个类对象,并放在spring容器管理。
-
而springFactories 配合使用spring的自动装载EnableAutoConfiguration 就可以达到类似@Bean注解的作用了。
-
有的人就会问,要对象,我直接@Bean创建,或者@Component,@Service不香嘛,还要搞spring.factories文件,麻烦。
是的,如果在自己项目开发确实没必要,但是如果你写的是一个sdk呢,一个工具呢,别人是引用jar包,当然要先把对象创建好放入spring容器中,不可能需要引用人自己注入spring吧。 -
例子:
spring启动中,是扫描application启动类所在的包下,将测试类提到 启动类所在包之外,因此,spring启动讲道理是不会扫描到。
public interface IUserService { } public class UserService implements IUserService { } public class UserService2 implements IUserService { }
而且上面的类都没有加任何注解,spring.factories文件如下:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ com.example.spring_factory_test.UserService,\ com.example.spring_factory_test.UserService2
准备测试类:
// spring启动之后执行该方法 @Component public class Testdemo implements ApplicationRunner { // 原来UserService,没有加任何注解,现在直接注入 @Autowired private UserService userService; @Override public void run(ApplicationArguments args) throws Exception { System.out.println(userService); } }
从截图可以看出,spring容器中有UserSerivce对象。
若把spring.factories文件内容注释掉,如下结果:
4. 详细源码解读
- 请看:https://blog.csdn.net/xueyijin/article/details/122833544