zl程序教程

您现在的位置是:首页 >  其它

当前栏目

SpringFactories

2023-06-13 09:18:13 时间

是Spring框架中的一个工厂类加载机制,它通过在META-INF/spring.factories文件中定义实现特定接口的类的全限定名,使得能够动态地将这些类加载到应用程序中。下面我们将结合Jvm类的加载机制进行详细解释和代码示例。

一、Jvm类的加载机制

Jvm在运行Java程序时,会按照以下顺序加载类:

1.Bootstrap ClassLoader:负责加载JVM核心类,如java.lang包下的类等;

2.Extension ClassLoader:负责加载JVM扩展类,如$JAVA_HOME/jre/lib/ext目录下的类等;

3.Application ClassLoader:负责加载用户自定义的类,也就是classpath下指定目录或jar包中的类。

二、SpringFactories工厂类加载机制详解 SpringFactories机制基于Java SPI(Service Provider Interface)进行设计,并且通过META-INF/spring.factories文件来定义实现特定接口的类的全限定名,以此达到加载特定的实现类的目的。

  1. 创建接口及其实现类

示例中我们先创建一个HelloWorldService接口及其实现类DefaultHelloWorldServiceImpl。

public interface HelloWorldService {
    String sayHello();
}

public class DefaultHelloWorldServiceImpl implements HelloWorldService {

    @Override
    public String sayHello() {
        return "Hello, World!";
    }
}
  1. 在META-INF/spring.factories中定义实现类

在META-INF/spring.factories文件中定义实现类的全限定名。

com.example.demo.HelloWorldService=\
    com.example.demo.DefaultHelloWorldServiceImpl
  1. 加载并使用实现类

通过以下代码可以加载这个实现类。

public class Main {
    public static void main(String[] args) {
        ServiceLoader<HelloWorldService> serviceLoader = ServiceLoader.load(HelloWorldService.class);
        for (HelloWorldService service : serviceLoader) {
            System.out.println(service.sayHello()); // 输出: Hello, World!
        }
    }
}
  1. 执行结果

运行Main类即可输出“Hello, World!”字符串。

三、SpringFactories+Jvm类加载机制示例

  1. 创建接口及其实现类
public interface UserService {
    String getName();
}

public class DefaultUserServiceImpl implements UserService {

    @Override
    public String getName() {
        return "ChatGPT";
    }
}
  1. 在META-INF/spring.factories中定义实现类
properties
com.example.demo.UserService=\
    com.example.demo.DefaultUserServiceImpl

  1. 写一个Main类,使用ClassLoader来模拟自定义类加载器
public class Main {
    public static void main(String[] args) throws Exception {
        MyClassLoader classLoader = new MyClassLoader();
        Class<?> userServiceClass = classLoader.loadClass("com.example.demo.DefaultUserServiceImpl");
        UserService userService = (UserService)userServiceClass.newInstance();
        System.out.println(userService.getName()); // 输出:ChatGPT
    }
}

class MyClassLoader extends ClassLoader {

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
        InputStream inputStream = this.getClass().getResourceAsStream(fileName);
        if (inputStream == null) {
            return super.findClass(name);
        }
        byte[] b;
        try {
            b = new byte[inputStream.available()];
            inputStream.read(b);
            return defineClass(name, b, 0, b.length);
        } catch (IOException e) {
            throw new ClassNotFoundException(name);
        }
    }
}
  1. 执行结果

运行Main类即可输出“ChatGPT”字符串。