Spring源码简易手写实现(学习过程记录)(一)

Spring源码简易手写实现(学习过程记录)(一)

com.rainwood包下建liming和spring包,spring包下存放手写的spring源码,liming用于测试

1.1创建spring 配置类和测试类

package com.rainwood.liming;

import com.rainwood.spring.ComponentScan;

@ComponentScan("com.liming.service")
public class AppConfig {
}

测试类Test

spring从ApplicationContext容器中加载配置类,将所有的bean加载到容器中,这个过程,肯定首先要建立配置类,从配置类中获取

package com.rainwood.liming;
import com.rainwood.spring.limingApplicationContext;
public class test {
    public static void main(String[] args) throws ClassNotFoundException {
        limingApplicationContext context = new limingApplicationContext(AppConfig.class);
        Object bean = context.getBean("userService");
    }
}

limingApplicationContext容器

package com.rainwood.spring;

import java.io.File;
import java.lang.annotation.Annotation;
import java.net.URL;

public class limingApplicationContext {
    private  Class configClass;

    public limingApplicationContext(Class configClass) throws ClassNotFoundException {
        this.configClass = configClass;

        //解析配置类
        //ComponentScan注解--》扫描路径
        ComponentScan componentScanAnnotation = (ComponentScan) configClass.getDeclaredAnnotation(ComponentScan.class);
        String path = componentScanAnnotation.value(); //扫描路径
        System.out.println("hhhhhhhhhhhhhhhh");
        System.out.println(path);
        path = path.substring(path.indexOf("liming"));
        System.out.println(path);
        path = "com.rainwood." + path;

        System.out.println("hhhhhhhhhhhhhhhh");
        path = path.replace(".","/");

        System.out.println(path);
        //扫描
        //类加载器:
        //Bootstrap -->jre/lib
        //Ext----->jre/ext/lib
        //App---->classpath
        ClassLoader classLoader = limingApplicationContext.class.getClassLoader(); //app 取得的是classpath对应的类加载器
        //resource对应的是一个目录 file:/D:/spring%e6%ba%90%e7%a0%81%e5%ad%a6%e4%b9%a0/target/classes/com/rainwood/liming/service
        URL resource = classLoader.getResource(path);
        File file = new File(resource.getFile());

        //判断是不是一个目录
        if(file.isDirectory()) {
            //可以获取到这个目录下所有的编译好的class文件路径
            File[] files = file.listFiles();
            for (File file1 : files) {
                System.out.println(file1);

                //D:\springResourceLearn\target\classes\com\rainwood\liming\service\UserService.class 转化成com.rainwood.liming.service.UserService
                String fileName = file1.getAbsolutePath();

                //判断是不是class文件再进一步处理
                if(fileName.endsWith(".class")) {
                    String className = fileName.substring(fileName.indexOf("com"),fileName.indexOf(".class"));
                    className = className.replace("\\",".");

                    try {
                        //这个地方不是放的class文件的url,而是这个类的全限定名
                        Class<?> aClass = classLoader.loadClass(className);
                        //判断这个类是不是有Component注解
                        if(aClass.isAnnotationPresent(Component.class)) {
                            System.out.println(className);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }

            }

        }

    }

    public Object getBean(String beanName) {
        return null;
    }
}

实体类

package com.rainwood.liming.service;

import com.rainwood.spring.Component;

@Component("userService")
public class UserService {
}

1.2 注解实现

Component注解

package com.rainwood.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
    String value() default "";
}

ComponentScan注解

package com.rainwood.spring;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
//    String value() default "";
    //没有defult的话,value属性必须传值
    String value();
}

其中String value()后的defult代表是否value属性有默认值,如果没有defult的话,在给类添加注解时,value属性不可以缺省。

posted @ 2021-10-22 16:13  rainbring  阅读(177)  评论(0)    收藏  举报