是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文件来定义实现特定接口的类的全限定名,以此达到加载特定的实现类的目的。
- 创建接口及其实现类
示例中我们先创建一个HelloWorldService接口及其实现类DefaultHelloWorldServiceImpl。
代码语言:javascript复制public interface HelloWorldService {
String sayHello();
}
public class DefaultHelloWorldServiceImpl implements HelloWorldService {
@Override
public String sayHello() {
return "Hello, World!";
}
}
- 在META-INF/spring.factories中定义实现类
在META-INF/spring.factories文件中定义实现类的全限定名。
代码语言:javascript复制com.example.demo.HelloWorldService=
com.example.demo.DefaultHelloWorldServiceImpl
- 加载并使用实现类
通过以下代码可以加载这个实现类。
代码语言:javascript复制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!
}
}
}
- 执行结果
运行Main类即可输出“Hello, World!”字符串。
三、SpringFactories Jvm类加载机制示例
- 创建接口及其实现类
public interface UserService {
String getName();
}
public class DefaultUserServiceImpl implements UserService {
@Override
public String getName() {
return "ChatGPT";
}
}
- 在META-INF/spring.factories中定义实现类
properties
com.example.demo.UserService=
com.example.demo.DefaultUserServiceImpl
- 写一个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);
}
}
}
- 执行结果
运行Main类即可输出“ChatGPT”字符串。