├── README.md ├── pom.xml ├── src └── main │ ├── java │ └── top │ │ └── guoziyang │ │ ├── main │ │ ├── Main.java │ │ ├── controller │ │ │ └── TestController.java │ │ └── service │ │ │ ├── AgentMethods.java │ │ │ ├── HelloWorldService.java │ │ │ ├── HelloWorldServiceImpl.java │ │ │ └── WrapService.java │ │ └── springframework │ │ ├── annotation │ │ ├── Autowired.java │ │ ├── Component.java │ │ ├── Controller.java │ │ ├── Qualifier.java │ │ ├── RequestMapping.java │ │ ├── RequestParam.java │ │ ├── Scope.java │ │ └── Value.java │ │ ├── context │ │ ├── AbstractApplicationContext.java │ │ ├── ApplicationContext.java │ │ └── ClassPathXmlApplicationContext.java │ │ ├── entity │ │ ├── BeanDefinition.java │ │ ├── BeanReference.java │ │ ├── PropertyValue.java │ │ └── PropertyValues.java │ │ ├── factory │ │ ├── AbstractBeanFactory.java │ │ ├── AutowiredCapableBeanFactory.java │ │ └── BeanFactory.java │ │ ├── io │ │ ├── Resource.java │ │ ├── ResourceLoader.java │ │ └── UrlResource.java │ │ ├── reader │ │ ├── AbstractBeanDefinitionReader.java │ │ ├── BeanDefinitionReader.java │ │ └── XmlBeanDefinitionReader.java │ │ └── web │ │ └── DispatcherServlet.java │ └── resources │ ├── application-annotation.xml │ ├── application.properties │ └── application.xml └── web └── WEB-INF └── web.xml /README.md: -------------------------------------------------------------------------------- 1 | # My-Spring-IOC 2 | Spring IOC容器的一个简单的实现,内含有一个简单的仿Spring MVC框架 3 | 4 | ### 目前已实现: 5 | - xml配置文件读取 6 | - 属性注入 7 | - 引用依赖注入 8 | - 递归引用注入 9 | - singleton与prototype模式注入 10 | - 注解配置 11 | - 简单的SpringMVC的实现 12 | 13 | ### TODO: 14 | - AOP实现 15 | - 循环依赖 16 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 4.0.0 6 | 7 | top.guoziyang 8 | My-Spring-IOC 9 | 1.0-SNAPSHOT 10 | 11 | 12 | 13 | cglib 14 | cglib 15 | 3.3.0 16 | 17 | 18 | javax.servlet 19 | javax.servlet-api 20 | 4.0.1 21 | provided 22 | 23 | 24 | 25 | 26 | 27 | 28 | org.apache.maven.plugins 29 | maven-compiler-plugin 30 | 3.8.1 31 | 32 | 1.8 33 | 1.8 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/Main.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main; 2 | 3 | import top.guoziyang.main.service.HelloWorldService; 4 | import top.guoziyang.main.service.WrapService; 5 | import top.guoziyang.springframework.context.ApplicationContext; 6 | import top.guoziyang.springframework.context.ClassPathXmlApplicationContext; 7 | 8 | public class Main { 9 | 10 | public static void main(String[] args) throws Exception { 11 | xmlTest(); 12 | } 13 | 14 | public static void xmlTest() throws Exception { 15 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml"); 16 | WrapService wrapService = (WrapService) applicationContext.getBean("wrapService"); 17 | wrapService.say(); 18 | HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService"); 19 | HelloWorldService helloWorldService2 = (HelloWorldService) applicationContext.getBean("helloWorldService"); 20 | System.out.println("prototype验证:相等" + (helloWorldService == helloWorldService2)); 21 | WrapService wrapService2 = (WrapService) applicationContext.getBean("wrapService"); 22 | System.out.println("singleton验证:相等" + (wrapService == wrapService2)); 23 | } 24 | 25 | public static void annotationTest() throws Exception { 26 | ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-annotation.xml"); 27 | WrapService wrapService = (WrapService) applicationContext.getBean("wrapService"); 28 | wrapService.say(); 29 | HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService"); 30 | HelloWorldService helloWorldService2 = (HelloWorldService) applicationContext.getBean("helloWorldService"); 31 | System.out.println("prototype验证:相等" + (helloWorldService == helloWorldService2)); 32 | WrapService wrapService2 = (WrapService) applicationContext.getBean("wrapService"); 33 | System.out.println("singleton验证:相等" + (wrapService == wrapService2)); 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/controller/TestController.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main.controller; 2 | 3 | import top.guoziyang.main.service.HelloWorldService; 4 | import top.guoziyang.springframework.annotation.Autowired; 5 | import top.guoziyang.springframework.annotation.Controller; 6 | import top.guoziyang.springframework.annotation.RequestMapping; 7 | import top.guoziyang.springframework.annotation.RequestParam; 8 | 9 | import javax.servlet.http.HttpServletRequest; 10 | import javax.servlet.http.HttpServletResponse; 11 | import java.io.IOException; 12 | 13 | @Controller 14 | @RequestMapping("/test") 15 | public class TestController { 16 | 17 | @Autowired 18 | private HelloWorldService helloWorldService; 19 | 20 | @RequestMapping("/test1") 21 | public void test1(HttpServletRequest request, HttpServletResponse response, 22 | @RequestParam("param") String param) { 23 | try { 24 | String text = helloWorldService.getString(); 25 | response.getWriter().write(text + " and the param is " + param); 26 | } catch (IOException e) { 27 | e.printStackTrace(); 28 | } 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/service/AgentMethods.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main.service; 2 | 3 | public class AgentMethods { 4 | 5 | public void before() { 6 | System.out.println("方法执行前"); 7 | } 8 | 9 | public void after() { 10 | System.out.println("方法执行后"); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/service/HelloWorldService.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main.service; 2 | 3 | public interface HelloWorldService { 4 | 5 | void saySomething(); 6 | 7 | String getString(); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/service/HelloWorldServiceImpl.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main.service; 2 | 3 | import top.guoziyang.springframework.annotation.Component; 4 | import top.guoziyang.springframework.annotation.Scope; 5 | import top.guoziyang.springframework.annotation.Value; 6 | 7 | @Component(name = "helloWorldService") 8 | @Scope("prototype") 9 | public class HelloWorldServiceImpl implements HelloWorldService { 10 | 11 | @Value("Hello world") 12 | private String text; 13 | 14 | @Override 15 | public void saySomething() { 16 | System.out.println(text); 17 | } 18 | 19 | @Override 20 | public String getString() { 21 | return text; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/main/service/WrapService.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.main.service; 2 | 3 | import top.guoziyang.springframework.annotation.Autowired; 4 | import top.guoziyang.springframework.annotation.Component; 5 | 6 | @Component(name = "wrapService") 7 | public class WrapService { 8 | 9 | @Autowired 10 | private HelloWorldService helloWorldService; 11 | 12 | public void say() { 13 | helloWorldService.saySomething(); 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Autowired.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface Autowired{ 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Component.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface Component { 11 | 12 | String name() default ""; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Controller.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.TYPE) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface Controller { 11 | 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Qualifier.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface Qualifier { 11 | 12 | String value(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/RequestMapping.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target({ElementType.TYPE, ElementType.METHOD}) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface RequestMapping { 11 | 12 | String value() default ""; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/RequestParam.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Target(ElementType.PARAMETER) 9 | @Retention(RetentionPolicy.RUNTIME) 10 | public @interface RequestParam { 11 | 12 | String value(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Scope.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.TYPE) 10 | public @interface Scope { 11 | 12 | String value() default "singleton"; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/annotation/Value.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.annotation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target(ElementType.FIELD) 10 | public @interface Value { 11 | 12 | public String value(); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/context/AbstractApplicationContext.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.context; 2 | 3 | import top.guoziyang.springframework.factory.BeanFactory; 4 | 5 | public abstract class AbstractApplicationContext implements ApplicationContext { 6 | 7 | BeanFactory beanFactory; 8 | 9 | @Override 10 | public Object getBean(Class clazz) throws Exception { 11 | return beanFactory.getBean(clazz); 12 | } 13 | 14 | @Override 15 | public Object getBean(String beanName) throws Exception { 16 | return beanFactory.getBean(beanName); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/context/ApplicationContext.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.context; 2 | 3 | /** 4 | * 应用程序上下文接口 5 | * 6 | * @author ziyang 7 | */ 8 | public interface ApplicationContext { 9 | 10 | Object getBean(Class clazz) throws Exception; 11 | 12 | Object getBean(String beanName) throws Exception; 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/context/ClassPathXmlApplicationContext.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.context; 2 | 3 | import top.guoziyang.springframework.entity.BeanDefinition; 4 | import top.guoziyang.springframework.factory.AbstractBeanFactory; 5 | import top.guoziyang.springframework.factory.AutowiredCapableBeanFactory; 6 | import top.guoziyang.springframework.io.ResourceLoader; 7 | import top.guoziyang.springframework.reader.XmlBeanDefinitionReader; 8 | 9 | import java.util.Map; 10 | 11 | public class ClassPathXmlApplicationContext extends AbstractApplicationContext { 12 | 13 | private final Object startupShutdownMonitor = new Object(); 14 | private String location; 15 | 16 | public ClassPathXmlApplicationContext(String location) throws Exception { 17 | super(); 18 | this.location = location; 19 | refresh(); 20 | } 21 | 22 | public void refresh() throws Exception { 23 | synchronized (startupShutdownMonitor) { 24 | AbstractBeanFactory beanFactory = obtainBeanFactory(); 25 | prepareBeanFactory(beanFactory); 26 | this.beanFactory = beanFactory; 27 | } 28 | } 29 | 30 | private void prepareBeanFactory(AbstractBeanFactory beanFactory) throws Exception { 31 | beanFactory.populateBeans(); 32 | } 33 | 34 | public void addNewBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception { 35 | XmlBeanDefinitionReader.processAnnotationProperty(beanDefinition.getBeanClass(), beanDefinition); 36 | beanFactory.registerBeanDefinition(name, beanDefinition); 37 | } 38 | 39 | public void refreshBeanFactory() throws Exception { 40 | prepareBeanFactory((AbstractBeanFactory) beanFactory); 41 | } 42 | 43 | private AbstractBeanFactory obtainBeanFactory() throws Exception { 44 | XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(new ResourceLoader()); 45 | beanDefinitionReader.loadBeanDefinitions(location); 46 | AbstractBeanFactory beanFactory = new AutowiredCapableBeanFactory(); 47 | for (Map.Entry beanDefinitionEntry : beanDefinitionReader.getRegistry().entrySet()) { 48 | beanFactory.registerBeanDefinition(beanDefinitionEntry.getKey(), beanDefinitionEntry.getValue()); 49 | } 50 | return beanFactory; 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/entity/BeanDefinition.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.entity; 2 | 3 | /** 4 | * 从配置文件中读取的Bean的定义 5 | * 6 | * @author ziyang 7 | */ 8 | public class BeanDefinition { 9 | 10 | private Object bean; 11 | private Class beanClass; 12 | private String beanClassName; 13 | private Boolean singleton; 14 | private PropertyValues propertyValues; 15 | 16 | public Object getBean() { 17 | return bean; 18 | } 19 | 20 | public void setBean(Object bean) { 21 | this.bean = bean; 22 | } 23 | 24 | public Class getBeanClass() { 25 | return beanClass; 26 | } 27 | 28 | public void setBeanClass(Class beanClass) { 29 | this.beanClass = beanClass; 30 | } 31 | 32 | public String getBeanClassName() { 33 | return beanClassName; 34 | } 35 | 36 | public void setBeanClassName(String beanClassName) { 37 | this.beanClassName = beanClassName; 38 | try { 39 | this.beanClass = Class.forName(beanClassName); 40 | } catch (ClassNotFoundException e) { 41 | e.printStackTrace(); 42 | } 43 | } 44 | 45 | public PropertyValues getPropertyValues() { 46 | if(propertyValues == null) { 47 | propertyValues = new PropertyValues(); 48 | } 49 | return propertyValues; 50 | } 51 | 52 | public void setPropertyValues(PropertyValues propertyValues) { 53 | this.propertyValues = propertyValues; 54 | } 55 | 56 | public Boolean isSingleton() { 57 | return singleton; 58 | } 59 | 60 | public void setSingleton(Boolean singleton) { 61 | this.singleton = singleton; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/entity/BeanReference.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.entity; 2 | 3 | /** 4 | * 注入类型为引用的定义 5 | * 6 | * @author ziyang 7 | */ 8 | public class BeanReference { 9 | 10 | private String name; 11 | private Object bean; 12 | 13 | public BeanReference(String name) { 14 | this.name = name; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | public void setName(String name) { 22 | this.name = name; 23 | } 24 | 25 | public Object getBean() { 26 | return bean; 27 | } 28 | 29 | public void setBean(Object bean) { 30 | this.bean = bean; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/entity/PropertyValue.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.entity; 2 | 3 | /** 4 | * 单个键值对,表示注入对象的属性 5 | * 6 | * @author ziyang 7 | */ 8 | public class PropertyValue { 9 | 10 | private final String name; 11 | private final Object value; 12 | 13 | public PropertyValue(String name, Object value) { 14 | this.name = name; 15 | this.value = value; 16 | } 17 | 18 | public String getName() { 19 | return name; 20 | } 21 | 22 | public Object getValue() { 23 | return value; 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/entity/PropertyValues.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.entity; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | /** 7 | * 键值对组,表示注入对象的属性 8 | * 9 | * @author ziyang 10 | */ 11 | public class PropertyValues { 12 | 13 | private final List propertyValueList = new ArrayList<>(); 14 | 15 | public PropertyValues() {} 16 | 17 | public void addPropertyValue(PropertyValue propertyValue) { 18 | propertyValueList.add(propertyValue); 19 | } 20 | 21 | public List getPropertyValues() { 22 | return propertyValueList; 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/factory/AbstractBeanFactory.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.factory; 2 | 3 | import top.guoziyang.springframework.entity.BeanDefinition; 4 | 5 | import java.util.Map; 6 | import java.util.concurrent.ConcurrentHashMap; 7 | 8 | public abstract class AbstractBeanFactory implements BeanFactory { 9 | 10 | ConcurrentHashMap beanDefinitionMap = new ConcurrentHashMap<>(); 11 | 12 | @Override 13 | public Object getBean(String name) throws Exception { 14 | BeanDefinition beanDefinition = beanDefinitionMap.get(name); 15 | if(beanDefinition == null) { 16 | throw new RuntimeException("Unable to find the bean of this name, please check!"); 17 | } 18 | if(!beanDefinition.isSingleton() || beanDefinition.getBean() == null) { 19 | return doCreateBean(beanDefinition); 20 | } else { 21 | return doCreateBean(beanDefinition); 22 | } 23 | } 24 | 25 | @Override 26 | public Object getBean(Class clazz) throws Exception { 27 | BeanDefinition beanDefinition = null; 28 | for(Map.Entry entry : beanDefinitionMap.entrySet()) { 29 | Class tmpClass = entry.getValue().getBeanClass(); 30 | if(tmpClass == clazz || clazz.isAssignableFrom(tmpClass)) { 31 | beanDefinition = entry.getValue(); 32 | } 33 | } 34 | if(beanDefinition == null) { 35 | throw new RuntimeException("Unable to find the bean of this class, please check!"); 36 | } 37 | if(!beanDefinition.isSingleton() || beanDefinition.getBean() == null) { 38 | return doCreateBean(beanDefinition); 39 | } else { 40 | return beanDefinition.getBean(); 41 | } 42 | } 43 | 44 | @Override 45 | public void registerBeanDefinition(String name, BeanDefinition beanDefinition) { 46 | beanDefinitionMap.put(name, beanDefinition); 47 | } 48 | 49 | /** 50 | * 创建Bean实例 51 | * @param beanDefinition Bean定义对象 52 | * @return Bean实例对象 53 | * @throws Exception 可能出现的异常 54 | */ 55 | abstract Object doCreateBean(BeanDefinition beanDefinition) throws Exception; 56 | 57 | public void populateBeans() throws Exception { 58 | for(Map.Entry entry : beanDefinitionMap.entrySet()) { 59 | doCreateBean(entry.getValue()); 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/factory/AutowiredCapableBeanFactory.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.factory; 2 | 3 | import top.guoziyang.springframework.entity.BeanDefinition; 4 | import top.guoziyang.springframework.entity.BeanReference; 5 | import top.guoziyang.springframework.entity.PropertyValue; 6 | 7 | import java.lang.reflect.Field; 8 | 9 | public class AutowiredCapableBeanFactory extends AbstractBeanFactory { 10 | 11 | @Override 12 | Object doCreateBean(BeanDefinition beanDefinition) throws Exception { 13 | if(beanDefinition.isSingleton() && beanDefinition.getBean() != null) { 14 | return beanDefinition.getBean(); 15 | } 16 | Object bean = beanDefinition.getBeanClass().newInstance(); 17 | if(beanDefinition.isSingleton()) { 18 | beanDefinition.setBean(bean); 19 | } 20 | applyPropertyValues(bean, beanDefinition); 21 | return bean; 22 | } 23 | 24 | /** 25 | * 为新创建了bean注入属性 26 | * @param bean 待注入属性的bean 27 | * @param beanDefinition bean的定义 28 | * @throws Exception 反射异常 29 | */ 30 | void applyPropertyValues(Object bean, BeanDefinition beanDefinition) throws Exception { 31 | for(PropertyValue propertyValue : beanDefinition.getPropertyValues().getPropertyValues()) { 32 | Field field = bean.getClass().getDeclaredField(propertyValue.getName()); 33 | Object value = propertyValue.getValue(); 34 | if(value instanceof BeanReference) { 35 | BeanReference beanReference = (BeanReference) propertyValue.getValue(); 36 | // 优先按照自定义名称匹配 37 | BeanDefinition refDefinition = beanDefinitionMap.get(beanReference.getName()); 38 | if(refDefinition != null) { 39 | if(!refDefinition.isSingleton() || refDefinition.getBean() == null) { 40 | value = doCreateBean(refDefinition); 41 | } else { 42 | value = refDefinition.getBean(); 43 | } 44 | } else { 45 | // 按照类型匹配,返回第一个匹配的 46 | Class clazz = Class.forName(beanReference.getName()); 47 | for(BeanDefinition definition : beanDefinitionMap.values()) { 48 | if(clazz.isAssignableFrom(definition.getBeanClass())) { 49 | if(!definition.isSingleton() || definition.getBean() == null) { 50 | value = doCreateBean(definition); 51 | } else { 52 | value = definition.getBean(); 53 | } 54 | } 55 | } 56 | } 57 | 58 | } 59 | if(value == null) { 60 | throw new RuntimeException("无法注入"); 61 | } 62 | field.setAccessible(true); 63 | field.set(bean, value); 64 | } 65 | } 66 | 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/factory/BeanFactory.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.factory; 2 | 3 | import top.guoziyang.springframework.entity.BeanDefinition; 4 | 5 | /** 6 | * Bean工厂接口 7 | * 8 | * @author ziyang 9 | */ 10 | public interface BeanFactory { 11 | 12 | /** 13 | * 根据名称从容器中获取bean 14 | * @param name bean的名字 15 | * @return bean实例对象 16 | */ 17 | Object getBean(String name) throws Exception; 18 | 19 | /** 20 | * 根据类从容器中获取bean 21 | * @param clazz bean的类对象 22 | * @return bean实例对象 23 | */ 24 | Object getBean(Class clazz) throws Exception; 25 | 26 | /** 27 | * 向工厂中注册bean定义 28 | * @param name bean的名字 29 | * @param beanDefinition bean的定义对象 30 | * @throws Exception 可能出现的异常 31 | */ 32 | void registerBeanDefinition(String name, BeanDefinition beanDefinition) throws Exception; 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/io/Resource.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.io; 2 | 3 | import java.io.InputStream; 4 | 5 | /** 6 | * 获取资源(配置文件)的接口 7 | * 8 | * @author ziyang 9 | */ 10 | public interface Resource { 11 | 12 | /** 13 | * 通过输入流的方式获取资源 14 | * @return 待获取资源的输入流 15 | * @throws Exception IO异常 16 | */ 17 | InputStream getInputStream() throws Exception; 18 | 19 | } 20 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/io/ResourceLoader.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.io; 2 | 3 | import java.net.URL; 4 | 5 | /** 6 | * 资源加载器,通过路径加载资源 7 | * 8 | * @author ziyang 9 | */ 10 | public class ResourceLoader { 11 | 12 | public Resource getResource(String location) { 13 | URL url = this.getClass().getClassLoader().getResource(location); 14 | return new UrlResource(url); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/io/UrlResource.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.io; 2 | 3 | import java.io.InputStream; 4 | import java.net.URL; 5 | import java.net.URLConnection; 6 | 7 | /** 8 | * 通过Url的方式获取资源 9 | * 10 | * @author ziyang 11 | */ 12 | public class UrlResource implements Resource { 13 | 14 | private URL url; 15 | 16 | public UrlResource(URL url) { 17 | this.url = url; 18 | } 19 | 20 | public InputStream getInputStream() throws Exception { 21 | URLConnection urlConnection = url.openConnection(); 22 | urlConnection.connect(); 23 | return urlConnection.getInputStream(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/reader/AbstractBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.reader; 2 | 3 | import top.guoziyang.springframework.entity.BeanDefinition; 4 | import top.guoziyang.springframework.io.ResourceLoader; 5 | 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | /** 10 | * BeanDefinitionReader实现的抽象类 11 | * 12 | * @author ziyang 13 | */ 14 | public abstract class AbstractBeanDefinitionReader implements BeanDefinitionReader { 15 | 16 | private Map registry; 17 | 18 | private ResourceLoader resourceLoader; 19 | 20 | public AbstractBeanDefinitionReader(ResourceLoader resourceLoader) { 21 | this.registry = new HashMap<>(); 22 | this.resourceLoader = resourceLoader; 23 | } 24 | 25 | public Map getRegistry() { 26 | return registry; 27 | } 28 | 29 | public ResourceLoader getResourceLoader() { 30 | return resourceLoader; 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/reader/BeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.reader; 2 | 3 | /** 4 | * Bean定义读取 5 | * 6 | * @author ziyang 7 | */ 8 | public interface BeanDefinitionReader { 9 | 10 | /** 11 | * 从某个位置读取Bean的配置 12 | * @param location 配置文件路径 13 | * @throws Exception 可能出现的异常 14 | */ 15 | void loadBeanDefinitions(String location) throws Exception; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/reader/XmlBeanDefinitionReader.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.reader; 2 | 3 | import org.w3c.dom.Document; 4 | import org.w3c.dom.Element; 5 | import org.w3c.dom.Node; 6 | import org.w3c.dom.NodeList; 7 | import top.guoziyang.springframework.annotation.*; 8 | import top.guoziyang.springframework.entity.BeanDefinition; 9 | import top.guoziyang.springframework.entity.BeanReference; 10 | import top.guoziyang.springframework.entity.PropertyValue; 11 | import top.guoziyang.springframework.io.ResourceLoader; 12 | 13 | import javax.xml.parsers.DocumentBuilder; 14 | import javax.xml.parsers.DocumentBuilderFactory; 15 | import java.io.File; 16 | import java.io.FileFilter; 17 | import java.io.IOException; 18 | import java.io.InputStream; 19 | import java.lang.reflect.Field; 20 | import java.net.JarURLConnection; 21 | import java.net.URL; 22 | import java.net.URLDecoder; 23 | import java.util.*; 24 | import java.util.jar.JarEntry; 25 | import java.util.jar.JarFile; 26 | 27 | /** 28 | * XML配置文件形式的Bean定义读取类 29 | * 30 | * @author ziyang 31 | */ 32 | public class XmlBeanDefinitionReader extends AbstractBeanDefinitionReader { 33 | 34 | public XmlBeanDefinitionReader(ResourceLoader resourceLoader) { 35 | super(resourceLoader); 36 | } 37 | 38 | @Override 39 | public void loadBeanDefinitions(String location) throws Exception { 40 | InputStream inputStream = getResourceLoader().getResource(location).getInputStream(); 41 | doLoadBeanDefinitions(inputStream); 42 | } 43 | 44 | protected void doLoadBeanDefinitions(InputStream inputStream) throws Exception { 45 | DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 46 | DocumentBuilder documentBuilder = factory.newDocumentBuilder(); 47 | Document document = documentBuilder.parse(inputStream); 48 | // 解析xml document并注册bean 49 | registerBeanDefinitions(document); 50 | inputStream.close(); 51 | } 52 | 53 | public void registerBeanDefinitions(Document document) { 54 | Element root = document.getDocumentElement(); 55 | // 从文件根递归解析 56 | parseBeanDefinitions(root); 57 | } 58 | 59 | protected void parseBeanDefinitions(Element root) { 60 | NodeList nodeList = root.getChildNodes(); 61 | // 确定是否注解配置 62 | String basePackage = null; 63 | for(int i = 0; i < nodeList.getLength(); i ++) { 64 | if(nodeList.item(i) instanceof Element) { 65 | Element ele = (Element)nodeList.item(i); 66 | if(ele.getTagName().equals("component-scan")) { 67 | basePackage = ele.getAttribute("base-package"); 68 | break; 69 | } 70 | } 71 | } 72 | if(basePackage != null) { 73 | parseAnnotation(basePackage); 74 | return; 75 | } 76 | for(int i = 0; i < nodeList.getLength(); i ++) { 77 | Node node = nodeList.item(i); 78 | if(node instanceof Element) { 79 | Element ele = (Element) node; 80 | if(ele.getTagName().equals("bean")) { 81 | processBeanDefinition(ele); 82 | } else if(ele.getTagName().equals("aop-config")){ 83 | processProxyDefinition(ele); 84 | } 85 | } 86 | } 87 | } 88 | 89 | protected void parseAnnotation(String basePackage) { 90 | Set> classes = getClasses(basePackage); 91 | for(Class clazz : classes) { 92 | processAnnotationBeanDefinition(clazz); 93 | } 94 | } 95 | 96 | protected void processAnnotationBeanDefinition(Class clazz) { 97 | if(clazz.isAnnotationPresent(Component.class)) { 98 | String name = clazz.getAnnotation(Component.class).name(); 99 | if(name == null || name.length() == 0) { 100 | name = clazz.getName(); 101 | } 102 | String className = clazz.getName(); 103 | boolean singleton = true; 104 | if(clazz.isAnnotationPresent(Scope.class) && "prototype".equals(clazz.getAnnotation(Scope.class).value())) { 105 | singleton = false; 106 | } 107 | BeanDefinition beanDefinition = new BeanDefinition(); 108 | processAnnotationProperty(clazz, beanDefinition); 109 | beanDefinition.setBeanClassName(className); 110 | beanDefinition.setSingleton(singleton); 111 | getRegistry().put(name, beanDefinition); 112 | } 113 | } 114 | 115 | public static void processAnnotationProperty(Class clazz, BeanDefinition beanDefinition) { 116 | 117 | Field[] fields = clazz.getDeclaredFields(); 118 | for(Field field : fields) { 119 | String name = field.getName(); 120 | if(field.isAnnotationPresent(Value.class)) { 121 | Value valueAnnotation = field.getAnnotation(Value.class); 122 | String value = valueAnnotation.value(); 123 | if(value != null && value.length() > 0) { 124 | // 优先进行值注入 125 | beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value)); 126 | } 127 | } else if(field.isAnnotationPresent(Autowired.class)) { 128 | if(field.isAnnotationPresent(Qualifier.class)) { 129 | Qualifier qualifier = field.getAnnotation(Qualifier.class); 130 | String ref = qualifier.value(); 131 | if(ref == null || ref.length() == 0) { 132 | throw new IllegalArgumentException("the value of Qualifier should not be null!"); 133 | } 134 | BeanReference beanReference = new BeanReference(ref); 135 | beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference)); 136 | } else { 137 | String ref = field.getType().getName(); 138 | BeanReference beanReference = new BeanReference(ref); 139 | beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference)); 140 | } 141 | } 142 | } 143 | 144 | } 145 | 146 | protected Set> getClasses(String packageName) { 147 | Set> classes = new LinkedHashSet<>(); 148 | boolean recursive = true; 149 | String packageDirName = packageName.replace('.', '/'); 150 | Enumeration dirs; 151 | try { 152 | dirs = Thread.currentThread().getContextClassLoader().getResources( 153 | packageDirName); 154 | // 循环迭代下去 155 | while (dirs.hasMoreElements()) { 156 | // 获取下一个元素 157 | URL url = dirs.nextElement(); 158 | // 得到协议的名称 159 | String protocol = url.getProtocol(); 160 | // 如果是以文件的形式保存在服务器上 161 | if ("file".equals(protocol)) { 162 | // 获取包的物理路径 163 | String filePath = URLDecoder.decode(url.getFile(), "UTF-8"); 164 | // 以文件的方式扫描整个包下的文件 并添加到集合中 165 | findAndAddClassesInPackageByFile(packageName, filePath, 166 | recursive, classes); 167 | } else if ("jar".equals(protocol)) { 168 | // 如果是jar包文件 169 | // 定义一个JarFile 170 | JarFile jar; 171 | try { 172 | // 获取jar 173 | jar = ((JarURLConnection) url.openConnection()) 174 | .getJarFile(); 175 | // 从此jar包 得到一个枚举类 176 | Enumeration entries = jar.entries(); 177 | // 同样的进行循环迭代 178 | while (entries.hasMoreElements()) { 179 | // 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件 180 | JarEntry entry = entries.nextElement(); 181 | String name = entry.getName(); 182 | // 如果是以/开头的 183 | if (name.charAt(0) == '/') { 184 | // 获取后面的字符串 185 | name = name.substring(1); 186 | } 187 | // 如果前半部分和定义的包名相同 188 | if (name.startsWith(packageDirName)) { 189 | int idx = name.lastIndexOf('/'); 190 | // 如果以"/"结尾 是一个包 191 | if (idx != -1) { 192 | // 获取包名 把"/"替换成"." 193 | packageName = name.substring(0, idx) 194 | .replace('/', '.'); 195 | } 196 | // 如果可以迭代下去 并且是一个包 197 | if ((idx != -1) || recursive) { 198 | // 如果是一个.class文件 而且不是目录 199 | if (name.endsWith(".class") 200 | && !entry.isDirectory()) { 201 | // 去掉后面的".class" 获取真正的类名 202 | String className = name.substring( 203 | packageName.length() + 1, name 204 | .length() - 6); 205 | try { 206 | // 添加到classes 207 | classes.add(Class 208 | .forName(packageName + '.' 209 | + className)); 210 | } catch (ClassNotFoundException e) { 211 | // log 212 | // .error("添加用户自定义视图类错误 找不到此类的.class文件"); 213 | e.printStackTrace(); 214 | } 215 | } 216 | } 217 | } 218 | } 219 | } catch (IOException e) { 220 | // log.error("在扫描用户定义视图时从jar包获取文件出错"); 221 | e.printStackTrace(); 222 | } 223 | } 224 | } 225 | } catch (IOException e) { 226 | e.printStackTrace(); 227 | } 228 | 229 | return classes; 230 | } 231 | 232 | private void findAndAddClassesInPackageByFile(String packageName, 233 | String packagePath, final boolean recursive, Set> classes) { 234 | // 获取此包的目录 建立一个File 235 | File dir = new File(packagePath); 236 | // 如果不存在或者 也不是目录就直接返回 237 | if (!dir.exists() || !dir.isDirectory()) { 238 | // log.warn("用户定义包名 " + packageName + " 下没有任何文件"); 239 | return; 240 | } 241 | // 如果存在 就获取包下的所有文件 包括目录 242 | File[] dirfiles = dir.listFiles(new FileFilter() { 243 | // 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件) 244 | public boolean accept(File file) { 245 | return (recursive && file.isDirectory()) 246 | || (file.getName().endsWith(".class")); 247 | } 248 | }); 249 | // 循环所有文件 250 | for (File file : dirfiles) { 251 | // 如果是目录 则继续扫描 252 | if (file.isDirectory()) { 253 | findAndAddClassesInPackageByFile(packageName + "." 254 | + file.getName(), file.getAbsolutePath(), recursive, 255 | classes); 256 | } else { 257 | // 如果是java类文件 去掉后面的.class 只留下类名 258 | String className = file.getName().substring(0, 259 | file.getName().length() - 6); 260 | try { 261 | // 添加到集合中去 262 | //classes.add(Class.forName(packageName + '.' + className)); 263 | //经过回复同学的提醒,这里用forName有一些不好,会触发static方法,没有使用classLoader的load干净 264 | classes.add(Thread.currentThread().getContextClassLoader().loadClass(packageName + '.' + className)); 265 | } catch (ClassNotFoundException e) { 266 | // log.error("添加用户自定义视图类错误 找不到此类的.class文件"); 267 | e.printStackTrace(); 268 | } 269 | } 270 | } 271 | } 272 | 273 | protected void processBeanDefinition(Element ele) { 274 | String name = ele.getAttribute("id"); 275 | String className = ele.getAttribute("class"); 276 | boolean singleton = true; 277 | if(ele.hasAttribute("scope") && "prototype".equals(ele.getAttribute("scope"))) { 278 | singleton = false; 279 | } 280 | BeanDefinition beanDefinition = new BeanDefinition(); 281 | processProperty(ele, beanDefinition); 282 | beanDefinition.setBeanClassName(className); 283 | beanDefinition.setSingleton(singleton); 284 | getRegistry().put(name, beanDefinition); 285 | } 286 | 287 | private void processProperty(Element ele, BeanDefinition beanDefinition) { 288 | NodeList propertyNode = ele.getElementsByTagName("property"); 289 | for(int i = 0; i < propertyNode.getLength(); i ++) { 290 | Node node = propertyNode.item(i); 291 | if(node instanceof Element) { 292 | Element propertyEle = (Element) node; 293 | String name = propertyEle.getAttribute("name"); 294 | String value = propertyEle.getAttribute("value"); 295 | if(value != null && value.length() > 0) { 296 | // 优先进行值注入 297 | beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, value)); 298 | } else { 299 | String ref = propertyEle.getAttribute("ref"); 300 | if(ref == null || ref.length() == 0) { 301 | throw new IllegalArgumentException("Configuration problem: element for property '" + name + "' must specify a ref or value"); 302 | } 303 | BeanReference beanReference = new BeanReference(ref); 304 | beanDefinition.getPropertyValues().addPropertyValue(new PropertyValue(name, beanReference)); 305 | } 306 | } 307 | } 308 | } 309 | 310 | protected void processProxyDefinition(Element ele) { 311 | 312 | } 313 | 314 | } 315 | -------------------------------------------------------------------------------- /src/main/java/top/guoziyang/springframework/web/DispatcherServlet.java: -------------------------------------------------------------------------------- 1 | package top.guoziyang.springframework.web; 2 | 3 | import top.guoziyang.springframework.annotation.Controller; 4 | import top.guoziyang.springframework.annotation.RequestMapping; 5 | import top.guoziyang.springframework.context.ClassPathXmlApplicationContext; 6 | import top.guoziyang.springframework.entity.BeanDefinition; 7 | 8 | import javax.servlet.ServletConfig; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.io.InputStream; 15 | import java.lang.reflect.Method; 16 | import java.net.URL; 17 | import java.util.*; 18 | 19 | public class DispatcherServlet extends HttpServlet { 20 | 21 | private Properties properties = new Properties(); 22 | 23 | private List classNames = new ArrayList<>(); 24 | 25 | private Map handlerMapping = new HashMap<>(); 26 | 27 | private HashSet classes = new HashSet<>(); 28 | 29 | private Map controllerMap = new HashMap<>(); 30 | 31 | private ClassPathXmlApplicationContext xmlApplicationContext; 32 | 33 | @Override 34 | public void init(ServletConfig config) { 35 | try { 36 | xmlApplicationContext = new ClassPathXmlApplicationContext("application-annotation.xml"); 37 | } catch (Exception e) { 38 | e.printStackTrace(); 39 | } 40 | doLoadConfig(config.getInitParameter("contextConfigLocation")); 41 | doScanner(properties.getProperty("scanPackage")); 42 | doInstance(); 43 | initHandlerMapping(); 44 | } 45 | 46 | @Override 47 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException { 48 | doPost(req, resp); 49 | } 50 | 51 | @Override 52 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException { 53 | try { 54 | //处理请求 55 | doDispatch(req, resp); 56 | } catch (Exception e) { 57 | resp.getWriter().write("500!! Server Exception"); 58 | } 59 | } 60 | 61 | public void doDispatch(HttpServletRequest request, HttpServletResponse response) throws Exception { 62 | if (handlerMapping.isEmpty()) return; 63 | String url = request.getRequestURI(); 64 | String contextPath = request.getContextPath(); 65 | url = url.replace(contextPath, "").replaceAll("/+", "/"); 66 | if (!handlerMapping.containsKey(url)) { 67 | response.getWriter().write("404 NOT FOUND!"); 68 | return; 69 | } 70 | Method method = handlerMapping.get(url); 71 | Class[] parameterTypes = method.getParameterTypes(); 72 | Map parameterMap = request.getParameterMap(); 73 | Object[] paramValues = new Object[parameterTypes.length]; 74 | for (int i = 0; i < parameterTypes.length; i++) { 75 | String requestParam = parameterTypes[i].getSimpleName(); 76 | if (requestParam.equals("HttpServletRequest")) { 77 | paramValues[i] = request; 78 | continue; 79 | } 80 | if (requestParam.equals("HttpServletResponse")) { 81 | paramValues[i] = response; 82 | continue; 83 | } 84 | if (requestParam.equals("String")) { 85 | for (Map.Entry param : parameterMap.entrySet()) { 86 | String value = Arrays.toString(param.getValue()).replaceAll("\\[|\\]", "").replaceAll(",\\s", ","); 87 | paramValues[i] = value; 88 | } 89 | } 90 | } 91 | try { 92 | method.invoke(controllerMap.get(url), paramValues); 93 | } catch (Exception e) { 94 | e.printStackTrace(); 95 | } 96 | } 97 | 98 | private void doLoadConfig(String location) { 99 | //把web.xml中的contextConfigLocation对应value值的文件加载到流里面 100 | InputStream resourceAsStream = this.getClass().getClassLoader().getResourceAsStream(location); 101 | 102 | try { 103 | //用Properties文件加载文件里的内容 104 | properties.load(resourceAsStream); 105 | } catch (IOException e) { 106 | e.printStackTrace(); 107 | } finally { 108 | if (null != resourceAsStream) { 109 | try { 110 | resourceAsStream.close(); 111 | } catch (IOException e) { 112 | e.printStackTrace(); 113 | } 114 | } 115 | } 116 | } 117 | 118 | private void doScanner(String packageName) { 119 | //把所有的.替换成/ 120 | URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.", "/")); 121 | File dir = new File(url.getFile()); 122 | for (File file : dir.listFiles()) { 123 | if (file.isDirectory()) { 124 | //递归读取包 125 | doScanner(packageName + "." + file.getName()); 126 | } else { 127 | String className = packageName + "." + file.getName().replace(".class", ""); 128 | classNames.add(className); 129 | } 130 | } 131 | } 132 | 133 | private void doInstance() { 134 | if (classNames.isEmpty()) { 135 | return; 136 | } 137 | for (String className : classNames) { 138 | try { 139 | //把类搞出来,反射来实例化(只有加@Controller需要实例化) 140 | Class clazz = Class.forName(className); 141 | if (clazz.isAnnotationPresent(Controller.class)) { 142 | classes.add(clazz); 143 | BeanDefinition definition = new BeanDefinition(); 144 | definition.setSingleton(true); 145 | definition.setBeanClassName(clazz.getName()); 146 | xmlApplicationContext.addNewBeanDefinition(clazz.getName(), definition); 147 | } 148 | } catch (Exception e) { 149 | e.printStackTrace(); 150 | } 151 | } 152 | try { 153 | xmlApplicationContext.refreshBeanFactory(); 154 | } catch (Exception e) { 155 | e.printStackTrace(); 156 | } 157 | } 158 | 159 | private void initHandlerMapping() { 160 | if (classes.isEmpty()) return; 161 | try { 162 | for (Class clazz : classes) { 163 | String baseUrl = ""; 164 | if (clazz.isAnnotationPresent(RequestMapping.class)) { 165 | baseUrl = clazz.getAnnotation(RequestMapping.class).value(); 166 | } 167 | Method[] methods = clazz.getMethods(); 168 | for (Method method : methods) { 169 | if (!method.isAnnotationPresent(RequestMapping.class)) continue; 170 | String url = method.getAnnotation(RequestMapping.class).value(); 171 | url = (baseUrl + "/" + url).replaceAll("/+", "/"); 172 | handlerMapping.put(url, method); 173 | controllerMap.put(url, xmlApplicationContext.getBean(clazz)); 174 | } 175 | } 176 | } catch (Exception e) { 177 | e.printStackTrace(); 178 | } 179 | } 180 | 181 | } 182 | -------------------------------------------------------------------------------- /src/main/resources/application-annotation.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | scanPackage=top.guoziyang.main.controller -------------------------------------------------------------------------------- /src/main/resources/application.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /web/WEB-INF/web.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | MySpringMVC 8 | top.guoziyang.springframework.web.DispatcherServlet 9 | 10 | contextConfigLocation 11 | application.properties 12 | 13 | 1 14 | 15 | 16 | MySpringMVC 17 | /* 18 | 19 | 20 | --------------------------------------------------------------------------------