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();
}
}
}