前言
提示:类加载器的作用主要是为了让Spring容器可以知道注解:
类加载器的作用主要是为了让Spring容器可以获得被注解修饰的类,放进Set集合中,元素为Class<?>。
一、类加载器是什么?
Spring容器其实就是这一块而已。所有的操作均是围绕下面这个简单集合,进行塞东西。
// 这就是Spring容器的大脑
Set<Class<?>> classSet = new HashSet<Class<?>>();
- 塞的东西都有什么呢?
就是我们常见的Service 类、Controller 类、Bean类、带有某注解的所有类等。 - 如何塞呢?
/**
* 获取应用包名下所有 Controller 类
*/
public static Set<Class<?>> getControllerClassSet() {
Set<Class<?>> classSet = new HashSet<Class<?>>();
for (Class<?> cls : CLASS_SET) {
if (cls.isAnnotationPresent(Controller.class)) {
classSet.add(cls);
}
}
return classSet;
}
/**
* 获取应用包名下所有 Bean 类(包括:Service、Controller 等)
*/
public static Set<Class<?>> getBeanClassSet() {
Set<Class<?>> beanClassSet = new HashSet<Class<?>>();
beanClassSet.addAll(getServiceClassSet());
beanClassSet.addAll(getControllerClassSet());
return beanClassSet;
}
- 塞进去后,如何进行实例化呢?
/**
* 创建实例
*/
public static Object newInstance(Class<?> cls) {
Object instance;
try {
instance = cls.newInstance();
} catch (Exception e) {
LOGGER.error("new instance failure", e);
throw new RuntimeException(e);
}
return instance;
}
- 塞进去后,如何能快速找到呢?
// 放到这个HashMap中,即可
private static final Map<Class<?>, Object> BEAN_MAP = new HashMap<Class<?>, Object>();
最后想象以下,我们上面初始的原始材料CLASS_SET是如何来的呢?
/**
* 获取指定包名下的所有类
*/
public static Set<Class<?>> getClassSet(String packageName) {
Set<Class<?>> classSet = new HashSet<Class<?>>();
try {
Enumeration<URL> urls = getClassLoader().getResources(packageName.replace(".", "/"));
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
if (url != null) {
String protocol = url.getProtocol();
if (protocol.equals("file")) {
String packagePath = url.getPath().replaceAll("%20", " ");
addClass(classSet, packagePath, packageName);
} else if (protocol.equals("jar")) {
JarURLConnection jarURLConnection = (JarURLConnection) url.openConnection();
if (jarURLConnection != null) {
JarFile jarFile = jarURLConnection.getJarFile();
if (jarFile != null) {
Enumeration<JarEntry> jarEntries = jarFile.entries();
while (jarEntries.hasMoreElements()) {
JarEntry jarEntry = jarEntries.nextElement();
String jarEntryName = jarEntry.getName();
if (jarEntryName.endsWith(".class")) {
String className = jarEntryName.substring(0, jarEntryName.lastIndexOf(".")).replaceAll("/", ".");
doAddClass(classSet, className);
}
}
}
}
}
}
}
} catch (Exception e) {
LOGGER.error("get class set failure", e);
throw new RuntimeException(e);
}
return classSet;
}
总结
提示:看到了?其实就是将类名放到set中,然后呢就是实例化放到HashMap,然后就注入了