简易Spring IOC实现

pom.xml的配置文件如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>spring1</groupId>
	<artifactId>test1</artifactId>
	<packaging>war</packaging>
	<version>0.0.1-SNAPSHOT</version>
	<name>test1 Maven Webapp</name>
	<url>http://maven.apache.org</url>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<!-- requied start -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.4</version>
			<scope>provided</scope>
		</dependency>
		<!-- requied end -->
	</dependencies>
	<build>
		<finalName>test1</finalName>
	</build>
</project>

application.properties的配置如下:

package=com.myTest

代码结构如下:

定义的标签

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
 * @Target:注解的作用目标
        
        @Target(ElementType.TYPE)   //接口、类、枚举、注解
        @Target(ElementType.FIELD) //字段、枚举的常量
        @Target(ElementType.METHOD) //方法
        @Target(ElementType.PARAMETER) //方法参数
        @Target(ElementType.CONSTRUCTOR)  //构造函数
        @Target(ElementType.LOCAL_VARIABLE)//局部变量
        @Target(ElementType.ANNOTATION_TYPE)//注解
        @Target(ElementType.PACKAGE) ///包   
 * @author an
 *
 */



//作用于 字段、枚举的常量
@Target({ElementType.FIELD})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyAutowired {
	public String value() default "";
}
package com.myTest.spring.Annotation;

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

//作用于 接口、类、枚举、注解
@Target({ElementType.TYPE})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyController {
	public String value() default "";
}

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//作用于接口、类、枚举、注解   和方法
@Target({ElementType.TYPE,ElementType.METHOD})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyRequestMapping {
	public String value() default "";
}

package com.myTest.spring.Annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
//方法参数
@Target({ElementType.PARAMETER})
//注解会在class字节码文件中存在,在运行时可以通过反射获取到
@Retention(RetentionPolicy.RUNTIME)
//说明该注解将被包含在javadoc中
@Documented
public @interface MyRequestParam {
	public String value() default "";
}

package com.myTest.spring.Annotation;

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

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

DispatchServlet的代码

package com.myTest.spring.Servlet;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.myTest.spring.Annotation.MyAutowired;
import com.myTest.spring.Annotation.MyController;
import com.myTest.spring.Annotation.MyService;

/**
 * 迷你Spring 
 * @author an
 *
 */
public class DispatchServlet extends HttpServlet{

	//加载配置文件
	private Properties contextConfig = new Properties();
	//放置注册的Bean
	private Map<String,Object> beanMap = new ConcurrentHashMap<String, Object>();
	//类的路径
	private List<String> classNames = new ArrayList<String>();


	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {

		doPost(req,resp);
	}

	@Override
	protected void doPost(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		System.out.println("----------doPost-----------");
	}

	@Override
	public void init(ServletConfig config) throws ServletException {

		//定位
		doLoadConfig(config.getInitParameter("contextConfigLocation"));
		//加载
		doScanner(contextConfig.getProperty("package"));
		//注册
		doRegister();
		//依赖注入
		doAutowired();

	}



	/**
	 * 依赖注入方法
	 */
	private void doAutowired() {
		if(beanMap.isEmpty()){
			return;
		}
		
		for(Map.Entry<String, Object> entry : beanMap.entrySet()){
			Field[] fields = entry.getValue().getClass().getDeclaredFields();
			
			for(Field f : fields){
				if(!f.isAnnotationPresent(MyAutowired.class)){
					continue;
				}
				MyAutowired myAutowired = f.getAnnotation(MyAutowired.class);
				String beanName = myAutowired.value();
				if("".equals(beanName)){
					beanName = f.getType().getName();
				}
				
				f.setAccessible(true);
				
				try {
					f.set(entry.getValue(), beanMap.get(beanName));
				} catch (Exception e) {
					e.printStackTrace();
				}
				
			}
			
		}
		
	}

	/**
	 * 注册方法
	 */
	private void doRegister() {
		if(classNames.isEmpty()){
			return ;
		}

		try {
			for(String className : classNames){
				Class<?> clazz = Class.forName(className);
				
				if(clazz.isAnnotationPresent(MyController.class)){
					String beanName = lowerFirstWord(clazz.getSimpleName());
					beanMap.put(beanName, clazz.newInstance());
				}else if(clazz.isAnnotationPresent(MyService.class)){
					MyService myService = clazz.getAnnotation(MyService.class);
					
					String beanName = myService.value();
					if("".equals(beanName)){
						beanName = lowerFirstWord(clazz.getSimpleName());
					}
					
					Object instance = clazz.newInstance();
					beanMap.put(beanName, instance);
				}else{
					continue;
				}
				
			}
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		}

	}

	/**
	 * 首字母小写
	 * @param simpleName
	 * @return
	 */
	private String lowerFirstWord(String simpleName) {
		char [] chars = simpleName.toCharArray();
		chars[0]+=32;
		return String.valueOf(chars);
	}

	/**
	 * 加载方法
	 * @param property
	 */
	private void doScanner(String property) {
		URL url = this.getClass().getClassLoader().getResource("/"+property.replaceAll("\\.", "/"));
		
		File fileDir = new File(url.getFile());
		
		for(File f : fileDir.listFiles()){
			if(f.isDirectory()){
				doScanner(property+ "." +f.getName());
				System.out.println(property+ "." +f.getName());
			}else{
				classNames.add(property+"."+f.getName().replace(".class", ""));
				//System.out.println(property+"."+f.getName().replace(".class", ""));
			}
		}
	}

	/**
	 * 加载配置文件,获取待扫描的路径
	 * @param location
	 */
	private void doLoadConfig(String location) {
		InputStream is = this.getClass().getClassLoader().getResourceAsStream(location.replace("classpath:", ""));
		
		try {
			contextConfig.load(is);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}





}

猜你喜欢

转载自blog.csdn.net/an341221/article/details/80376459