webee自己实现一个简单的mvc架构

5 篇文章 0 订阅

1、整体的目录:

在这里插入图片描述

首先定义一个类扫描器:

2、ClassScanner
package cn.com.hsl.webEE.utils;

import java.io.File;
import java.io.IOException;
import java.net.JarURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ClassScanner {

	public static Map<String, Class<?>> scan(String pkg) {
		Map<String, Class<?>> result = new HashMap<String, Class<?>>();
		String basePath = pkg;
		if (pkg.contains(".")) {
			basePath = pkg.replace(".", "/");
		}
		
		Enumeration<URL> urls;
		try {
			urls = Thread.currentThread().getContextClassLoader().getResources(basePath);
			while (urls.hasMoreElements()) {
				URL url = (URL) urls.nextElement();
				//如果是本地的文件
				if ("file".equals(url.getProtocol())) {
					File folder = new File(url.getPath());
					scanFolder(pkg, folder, result);
					
				//如果是Jar包的文件
				} else if ("jar".equals(url.getProtocol())) {
					scanjar(url, basePath, result);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
		return result;
	}
	
	private static void scanFolder(String root, File folder, Map<String, Class<?>> result) {
		for (File file : folder.listFiles()) {
			String name = file.getName();
			if (file.isDirectory()) {
				scanFolder(root + "." + name, file, result);
			} else {
				try {
					//只扫描以 .class 结尾的文件
					if (!name.endsWith(".class")) {
						continue;
					}
					String className = name.substring(0, name.lastIndexOf("."));
					
					//不掃描內部類
					if (className.matches("[\\w+$*\\w*/]+\\$\\d+$")) {
						continue;
					}
					String classPath = root + "." + className;
					result.put(className, Class.forName(classPath));
				} catch (ClassNotFoundException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	private static void scanjar(URL url, String basePath, Map<String, Class<?>> result) throws IOException {
		JarURLConnection connection = (JarURLConnection) url.openConnection();
		if (connection != null) {
			JarFile jarFile = connection.getJarFile();
			if (jarFile != null) {
			
				//Jar包获取的将是这个jar包中的全部文件
				Enumeration<JarEntry> entryEnu = jarFile.entries();
				while (entryEnu.hasMoreElements()) {
					JarEntry jarEntry = (JarEntry) entryEnu.nextElement();
					String entryClass = jarEntry.getName();
					if (entryClass == null || !entryClass.endsWith(".class")){
						continue;
					}
					
					String entryName = entryClass.substring(0, entryClass.lastIndexOf("."));
					if (entryName.matches("[\\w+$*\\w*/]+\\$\\d+$")) {
						continue;
					}
					
					//需要过滤其他包目录下的文件
					if (entryName.startsWith(basePath)) {
						try {
							result.put(entryName, Class.forName(entryName.replace("/", ".")));
						} catch (ClassNotFoundException e) {
							e.printStackTrace();
						}
					}
				}
			}
		}
	}
	
	public static void main(String[] args) {
		Map<String, Class<?>> classMap = ClassScanner.scan("cn");
		System.out.println(classMap);
	}
	
}

其次定义一些注解:

3.1、Autowired
package cn.com.hsl.webEE.annotation;

import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

@Retention(RUNTIME)
@Target({ TYPE, FIELD })
public @interface Autowired {
	//注入的Bean实例
	String value();
}
3.2、Bean
package cn.com.hsl.webEE.annotation;

import static java.lang.annotation.ElementType.TYPE;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

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

@Retention(RUNTIME)
@Target(TYPE)
public @interface Bean {
	//Bean在容器中的名称
	String value();
	//是否是单例
	boolean single() default true;
}

定义一些实体类,这些实体类用来保存 在多例的时候 类和属性的相关信息:

4.1、BeanEntity
package cn.com.hsl.webEE.entity;

import java.util.ArrayList;
import java.util.List;

public class BeanEntity {

	private String beanName;
	private String className;
	private Class<?> clazz;
	private List<FieldEntity> fields = new ArrayList<FieldEntity>();
	
	public String getBeanName() {
		return beanName;
	}
	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}
	public String getClassName() {
		return className;
	}
	public void setClassName(String className) {
		this.className = className;
	}
	public Class<?> getClazz() {
		return clazz;
	}
	public void setClazz(Class<?> clazz) {
		this.clazz = clazz;
	}
	public List<FieldEntity> getFields() {
		return fields;
	}
	public void setFields(List<FieldEntity> fields) {
		this.fields = fields;
	}
}
4.2、FieldEntity
package cn.com.hsl.webEE.entity;

import java.lang.reflect.Field;

public class FieldEntity {

	private Field field;
	private String beanName;
	
	public Field getField() {
		return field;
	}
	public void setField(Field field) {
		this.field = field;
	}
	public String getBeanName() {
		return beanName;
	}
	public void setBeanName(String beanName) {
		this.beanName = beanName;
	}
	
	
}

封装Bean工厂:

4、ApplicationContext
package cn.com.hsl.webEE.core;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import cn.com.hsl.webEE.annotation.Autowired;
import cn.com.hsl.webEE.annotation.Bean;
import cn.com.hsl.webEE.entity.BeanEntity;
import cn.com.hsl.webEE.entity.FieldEntity;
import cn.com.hsl.webEE.utils.ClassScanner;

public class ApplicationContext {

	private Map<String, Class<?>> classMap;
	
	//单例Bean容器
	private Map<String, Object> beans = new HashMap<String, Object>();
	
	//多例Bean容器
	private Map<String, BeanEntity> entities = new HashMap<String, BeanEntity>();
	
	public ApplicationContext(String pkg) {
		init(pkg);
	}
	
	private void init(String pkg) {
		this.classMap = ClassScanner.scan(pkg);
		for (Entry<String, Class<?>> entry : classMap.entrySet()) {
			//String beanName = entry.getKey();
			Class<?> beanClass = entry.getValue();
			if (beanClass.isAnnotationPresent(Bean.class)) {
				initBean(beanClass);
			}
		}
	}
	
	private Object initBean(Class<?> clazz) {
		Object obj = null;
		try {
			Bean bean = clazz.getAnnotation(Bean.class);
			String beanName = bean.value();
			
			//如果是单例
			if(bean.single()) {
				if (beans.containsKey(beanName)) {
					return beans.get(beanName);
				}
				
				obj = initSigleBean(clazz);
				beans.put(beanName, obj);
				
			//如果是多例,只是保存BeanEntity
			} else {
				initMultBean(beanName, clazz);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return obj;
	}
	
	private Object initSigleBean(Class<?> clazz) throws Exception {
		Object obj = clazz.newInstance();
		Field[] fields = clazz.getDeclaredFields();
		for (Field field : fields) {
			if (field.isAnnotationPresent(Autowired.class)) {
				Autowired autowired = field.getAnnotation(Autowired.class);
				String fieldBeanName = autowired.value();
				
				//从容器中去拿,如果有直接使用,如果没有,先去创建,再使用
				Object o = getBean(fieldBeanName);
				if (o == null) {
					
					//如果这个field是多例的,则没有返回具体的实例,而是一个beanEntity
					o = initBean(field.getType());
					
					//这时需要再次获取一次,实例化一下。
					if (o == null) {
						o = getBean(fieldBeanName);
					}
				}
				
				field.setAccessible(true);
				field.set(obj, o);
			}
		}
		
		return obj;
	}
	
	private void initMultBean(String beanName, Class<?> clazz) {
		Field[] fields = clazz.getDeclaredFields();
		BeanEntity beanEntity = new BeanEntity();
		beanEntity.setBeanName(beanName);
		beanEntity.setClazz(clazz);
		for (Field field : fields) {
			if (field.isAnnotationPresent(Autowired.class)) {
				Autowired autowired = field.getAnnotation(Autowired.class);
				FieldEntity fieldEntity = new FieldEntity();
				fieldEntity.setBeanName(autowired.value());
				fieldEntity.setField(field);
				beanEntity.getFields().add(fieldEntity);
			}
		}
		entities.put(beanName, beanEntity);
	}
	
	public Object getBean(String beanName) throws Exception {
		Object obj = null;
		obj = beans.get(beanName);
		if (obj == null) {
			if (entities.containsKey(beanName)) {
				BeanEntity beanEntity = entities.get(beanName);
				Class<?> clazz = beanEntity.getClazz();
				if (clazz != null) {
					obj = clazz.newInstance();
					List<FieldEntity> fieldEntities = beanEntity.getFields();
					for (FieldEntity fieldEntity : fieldEntities) {
						Field field = fieldEntity.getField();
						field.setAccessible(true);
						field.set(obj, getBean(fieldEntity.getBeanName()));
					}
				}
			}
		}
		return obj;
	}
}

测试:

5.1、UserDao
package cn.com.hsl.webEE;

import cn.com.hsl.webEE.annotation.Bean;

@Bean("userDao")
public class UserDao {

	public void addUser() {
		System.out.println(this.getClass().getName() + ".addUser().");
	}
	
}

5.2、UserService
package cn.com.hsl.webEE;

import cn.com.hsl.webEE.annotation.Autowired;
import cn.com.hsl.webEE.annotation.Bean;

@Bean("userservice")
public class UserService {

	@Autowired("userDao")
	private UserDao userDao;

	public void add() {
		userDao.addUser();
	}
}

5.3、App
package cn.com.hsl.webEE;

import cn.com.hsl.webEE.core.ApplicationContext;

/**
 * Hello world!
 *
 */
public class App {
	public static void main(String[] args) {
		try {
			ApplicationContext context = new ApplicationContext("cn.com.hsl");
			UserService userService = (UserService) context.getBean("userservice");
			userService.add();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值