目录
TestController类:
@Component
public class TestController {
@Autowired
private UserService userService;
public void test(){
userService.addUser("我口袋只剩玫瑰一片","此行又山高路远");
}
}
UserService类:
@Component
public class UserService {
public void addUser(String a,String b){
System.out.println(a);
System.out.println(b);
}
}
核心代码SpringIOC:
public class SpringIOC {
private List<String> beanNames;
private List<String> filePaths;
private String basePath;
private String basePackage;
private Map<String, Object> beans =new HashMap<>();
/**
* 扫描所有的文件信息信息,存到了 filePaths
*/
private void scan() throws FileNotFoundException {
File file = new File(basePath);
filePaths = new ArrayList<>();
if(file.exists()){
Queue<File> queue = new LinkedList<>();
queue.add(file);
while(!queue.isEmpty()){
File poll = queue.poll();
if(poll == null){
continue;
}
if(poll.isDirectory()){
File[] files = poll.listFiles();
for (File f : files) {
queue.add(f);
}
}else {
filePaths.add(poll.getPath());
}
}
}else {
throw new FileNotFoundException(basePath+" not found");
}
//将路径中所有的文件打印出来 filePaths.forEach(e-> System.out.println(e));
}
/**
* 讲所有的.java结尾的 全限定名放到 beanNames
*/
public void initBeanNames(){
for (String s : filePaths) {
String replace = s.replace(basePath, "");
if(replace.endsWith(".java")) {
replace = replace.substring(0, replace.length()-5);
}
char[] chars = replace.toCharArray();
for (int i = 0; i < chars.length; i++) {
if(chars[i]=='\\'){
chars[i] = '.';
}
}
beanNames.add(basePackage+"."+new String(chars));
}
beanNames.forEach(System.out::println);
}
public void initBeans(){
for (String beanName : beanNames) {
try {
Class<?> aClass = Class.forName(beanName);
Annotation[] declaredAnnotations = aClass.getDeclaredAnnotations();
for (Annotation declaredAnnotation : declaredAnnotations) {
if(declaredAnnotation instanceof Component){
//反射:
Object o = aClass.newInstance();
beans.put(aClass.getName(),o);
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException e) {
e.printStackTrace();
}
}
for (Map.Entry<String, Object> entry : beans.entrySet()) {
Field[] declaredFields = entry.getValue().getClass().getDeclaredFields();
for (Field field : declaredFields) {
Annotation[] declaredAnnotations = field.getDeclaredAnnotations();
for (Annotation annotation : declaredAnnotations) {
if(annotation instanceof Autowired){
//field 需要由我们来赋值
// 我们所持有的所有对象 在beans中
// 根据当前域中的类型的名字:反射
String name = field.getType().getName();
// 从beans 中获得对应的对象
Object o = beans.get(name);
field.setAccessible(true);
try {
field.set(entry.getValue(), o);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
}
}
public Object getInstance(String beanName) {
return beans.get(beanName);
}
private void initPath(){
basePath="D:\\imitateIOC\\src\\main\\java\\com\\test\\springioc\\";
basePackage="com.test.springioc";
}
public SpringIOC() {
initPath();
try {
scan();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
beanNames= new ArrayList<>();
initBeanNames();
}
}
Autowired和Component注解
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
SpringIOCTest 类
public class SpringIOCTest {
@Test
public void testIOC() throws FileNotFoundException {
//创建IOC容器
SpringIOC springIOC = new SpringIOC();
//初始化容器
springIOC.initBeans();
//从容器中获得TestController对象
TestController instance = (TestController) springIOC.getInstance(TestController.class.getName());
//调用其方法
instance.test();
}
}
总结:
整个环境可以归纳为两个阶段:
第一阶段:处理字符串,获得到类权限的名
第二阶段:根据类权限名创建对应的对象(带有@Component的类才会创建对应的对象),然后再遍历访问我们创建好的对象,判断所有的域是否带有@Autowired,如果有就从Bean中取出对应的对象设置进去。
通篇我们没有写new TestController,new UserService这种代码,都是由反射创建的对象设置进来,这就是这篇代码的基本逻辑。
源码已上传gitee平台:
https://gitee.com/dont-live-in-the-past/copy-ioc.git