总结
- IOC容器的本质是一个Map<Class,Object>
- Spring通过注解与反射对Bean进行实例化,并放到容器中
Code
package com.sc.bean;
public interface ApplicationContext {
public Object getBean(Class clazz);
}
package com.sc.bean;
import com.sc.annotation.Bean;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
public class AnnotationApplicationContext implements ApplicationContext{
private Map<Class,Object> beanFactory = new HashMap<>();
private String rootPath;
@Override
public Object getBean(Class clazz) {
return beanFactory.get(clazz);
}
/**
* 有参构造,传递包路径,扫描包以及子包
* @param basePackage
*/
public AnnotationApplicationContext(String basePackage) throws IOException {
// 获取包路径
String packageDirName = basePackage.replaceAll("\\.","\\\\");
// 获取包路径下的所有文件
Enumeration<URL> urls = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
while(urls.hasMoreElements()){
URL url = urls.nextElement();
String filePath = URLDecoder.decode(url.getPath(), "UTF-8");
rootPath = filePath.substring(0,filePath.length()-packageDirName.length());
loadBean(new File(filePath));
}
}
/**
* 递归扫描包,将@Bean注解的类实例化,加到IOC容器
* @param file
*/
private void loadBean(File file) {
// 判断file是否存在,若为空则退出递归
if(!file.exists()){
return;
}
if(file.isDirectory()){
File[] files = file.listFiles();
for(File f : files){
loadBean(f);
}
}else{
// 获取文件名
String fileName = file.getName();
// 获取文件后缀
String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
// 判断文件后缀是否为class
if("class".equals(suffix)){
String classFullName = getClassFullName(file, suffix);
loadBeanByReflect(classFullName);
}
}
}
/**
* 通过反射实例化指定的类
* @param classFullName
*/
private void loadBeanByReflect(String classFullName) {
try {
// 获取类
Class<?> clazz = Class.forName(classFullName);
// 判断类是否被注解
if(clazz.getAnnotation(Bean.class) != null){
// 实例化
Object bean = clazz.newInstance();
// 若clazz存在接口,则将接口作为key添加到beanFactory
if(clazz.getInterfaces().length>0){
beanFactory.put(clazz.getInterfaces()[0],bean);
}else{
beanFactory.put(clazz,bean);
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
/**
* 截取字符串,获取类全名
* @param file 文件名
* @param suffix 后缀
* @return 类全名
*/
private String getClassFullName(File file, String suffix) {
// 获取全类名 com.ayguigu.dao.Serivice
String absolutePath = file.getAbsolutePath();
String classFullName = absolutePath
.substring(rootPath.length()-1,absolutePath.length()- suffix.length()-1)
.replaceAll("\\\\","\\.");
return classFullName;
}
}