通过java反射实现的简易的spring ioc和springmvc的一部分功能,很多东西没有考虑进去,只是提供一种思路。
简易实现spring的ioc和springmvc.
思路:
模仿SpringMVC定义如下几个注解。
@Service:Service层注解;
@Controller:Controller注解;
@Autowired:自动注入依赖;
@RequestMapping:定义请求的url映射。
假定我们又UserController,定义如下:
@Contorller("user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/add")
public String add(User user) {
userService.insert(user);
return "/user";
}
@RequestMapping(value = "/showUserList.htm")
public ModelAndView showUserList(HttpServletRequest request,HttpServletResponse response) {
ModelAndView mv = new ModelAndView("/list");
List<User> users = userService.getAll();
mv.addObject("users",users);
return mv;
}
}
我们在系统启动时,就根据配置的basePackage扫描该基础包下所有的@Service和@Controller的类。
1.springioc部分,解决依赖注入问题
定义HashMap<String,Object>维护类的全限定名与实例对象的关系,将所有注解了@Service和@Controller的类初始化。
然后扫描所有注解的类,扫描所有的Field,如果是被@Autowired注解,则从上面的Map中取出实例对象进行设置。–》依赖注入
如果被@Autowired注解的是接口,则会遍历所有的@Service和@Controller的对象,找出其实现类,并注入。
2.springmvc部分,遍历所有上面的Map中的对象,如果是@Controller注解的类,则:
a.读取@Controller的value,即得到上面示例URL中的/user部分。
b.遍历所有的方法,如果是被@RequestMapping注解,则取出其value,即示例中的/add部分。
3.定义DispatcherServlet,作为所有请求的入口类
通过request.getRequestURI()获取到请求的uri,比如/myspring-mvc/user/add。通过request.getContextPath()获取到上下文名称,将uri中项目上下文去掉,即得到/user/add。
然后通过上面的springmvc部分的Map可以获取到Method,通过method.invoke方法调用Controller类的处理方法。可以参考Springmvc返回String或ModelAndView渲染页面。
如果返回String,即视图名称,可以根据String是否包括forward或redirect关键字,像springmvc一样进行forward或redirect处理。数据则根据request进行设置即可。
本例测试:
错误的URL测试:
http://localhost:8081/myspring-mvc/test/index2.htm
url可以随意写,只要不是/test/index.htm和/test/showUserList.htm都可以。
不带数据的测试:
http://localhost:8081/myspring-mvc/test/index.htm
带数据的测试:
http://localhost:8081/myspring-mvc/test/showUserList.htm,效果:
这里只是简易版本的实现,还有很多因素没有考虑,仅仅是结合反射来实现一个简易版的springmvc功能。
源代码:https://gitee.com/tommy88/my-test-projects下的myspring-mvc模块。