SpringFactoriesLoader.loadFactories()与SpringFactoriesLoader.loadFactoryNames() 详细使用方式

1. 前言

  1. SpringFactoriesLoader类的主要作用是通过类路径下的META-INF/spring.factories文件获取工厂类接口的实现类,初始化并保存在缓存中,以供Springboot启动过程中各个阶段的调用
  2. SpringFactoriesLoader.loadFactories():是根据参数factoryClass获取spring.factories下配置的所有实现类实例,返回List<T>的。
  3. SpringFactoriesLoader.loadFactoryNames():是根据参数factoryClass获取spring.factories下配置的所有实现类的全限定类名返回List<String>的。

2. 基本使用

  1. 先准备如下内容(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
    
  2. 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的使用

  1. 先思考一下,spring要提供这个springfactories的功能肯定有原因的。

  2. 如上面基本用法,SpringFactoriesLoader.loadFactories()方法可以直接创建类对象

  3. 对象哦,又是spring,这不得马上上到@Bean注解的作用,创建一个类对象,并放在spring容器管理。

  4. 而springFactories 配合使用spring的自动装载EnableAutoConfiguration 就可以达到类似@Bean注解的作用了。

  5. 有的人就会问,要对象,我直接@Bean创建,或者@Component,@Service不香嘛,还要搞spring.factories文件,麻烦。
    是的,如果在自己项目开发确实没必要,但是如果你写的是一个sdk呢,一个工具呢,别人是引用jar包,当然要先把对象创建好放入spring容器中,不可能需要引用人自己注入spring吧。

  6. 例子
    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. 详细源码解读

  1. 请看:https://blog.csdn.net/xueyijin/article/details/122833544
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值