├── 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 |
--------------------------------------------------------------------------------