1、目录结构

2、实现
package com.spring;
import java.io.File;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
public class ApplicationContext {
//用ConcurrentHashMap存储beandefinition
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<String, BeanDefinition>();
//单例池存放单例对象
private ConcurrentHashMap<String,Object> singletonObject = new ConcurrentHashMap<String, Object>();
public ApplicationContext(Class configClass){
//扫描类
List<Class> classList = scan(configClass);
for(Class clazz : classList){
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setBeanClass(clazz);
//获取注解,把注解的信息存放到beandefinition对象中,比如如果有component的话就说明它是一个bean
String beanName = null;
Scope scope = null;
if(clazz.isAnnotationPresent(Component.class)){
Component component = (Component) clazz.getAnnotation(Component.class);
beanName = component.value();
}
if(clazz.isAnnotationPresent(Scope.class)){
scope = (Scope) clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
}else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
//扫描类之后怎么创建类,比如componentscan则创建bean,还有就是是否是懒加载,单例等等
for(String beanName : beanDefinitionMap.keySet()){
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object bean = createBean(beanDefinition,beanName);
singletonObject.put(beanName,bean);
}
}
//生成单例bean------单例池
}
private Object createBean(BeanDefinition beanDefinition,String beanName) {
//生成bean
Class beanClass = beanDefinition.getBeanClass();
try{
//实例化
Object bean = beanClass.getDeclaredConstructor().newInstance();
//填充属性
Field[] fields = beanClass.getDeclaredFields();
for(Field field : fields){
if(field.isAnnotationPresent(Autowired.class)){
//调用getbean方法,getbean方法从单例池中找,如果没有找到那么就去创建bean
Object userService = getBean(field.getName());
field.setAccessible(true);
field.set(bean,userService);
}
}
//查看有没有实现BeanNameAware接口
if(bean instanceof BeanNameAware){
//实现方法
((BeanNameAware) bean).setBeanName(beanName);
}
//查看是否实现InitializingBean接口
if(bean instanceof InitializingBean){
//实现方法
((InitializingBean) bean).afterPropertiesSet();
}
return bean;
}catch (Exception e){
}
return null;
}
private List<Class> scan(Class configClass) {
//返回结构
List<Class> res = new ArrayList<Class>();
//是否存在compontscan注解
/* if(!configClass.isAnnotationPresent(ComponentScan.class)){
throw new RuntimeException("ERROR");
}*/
/*
拿到注解的value
*/
ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String scanPath = componentScan.value();
//修改路径的格式 //com.lzq.service =====> com/lzq/service
scanPath = scanPath.replace(".","/");
System.out.println(scanPath);
//如何扫描类
ClassLoader classLoader = ApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(scanPath);
//通过路径拿到该目录
File file = new File(resource.getFile());
//拿到该目录下的所有文件,包括类,xml等等 com/lzq/service
File[] files = file.listFiles();
for(File f : files){
System.out.println(f);
//拿到路径,修改路劲格式
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\",".");
System.out.println(absolutePath);
try {
//拿到路径,通过反射创建对象
Class<?> clazz = classLoader.loadClass(absolutePath);
res.add(clazz);
}catch (Exception e){
e.printStackTrace();
}
}
return res;
}
public Object getBean(String beanName){
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("prototype")){
return createBean(beanDefinition,beanName);
}else {
Object bean = singletonObject.get(beanName);
if(bean == null){
Object newBean = createBean(beanDefinition,beanName);
singletonObject.put(beanName,newBean);
return newBean;
}
return bean;
}
}
}
3、测试
import com.lzq.AppConfig;
import com.lzq.service.OrderService;
import com.spring.ApplicationContext;
import org.junit.Test;
public class test {
@Test
public void test(){
//启动Spring
ApplicationContext applicationContext = new ApplicationContext(AppConfig.class);
//getBean()
System.out.println(applicationContext.getBean("orderService"));
System.out.println(applicationContext.getBean("orderService"));
System.out.println(applicationContext.getBean("orderService"));
System.out.println(applicationContext.getBean("orderService"));
}
}
4、效果
