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属性不可以缺省。
浙公网安备 33010602011771号