SpringIOC
1.解析配置类Config.class,获取配置类上面@componetScan注解的值package
2.扫描package下的类,并把带有@Compent注解的以及继承自@Compent注解的类,解析成
beanDefintion(bean定义),解析类中定义的@Scope @Lazy 等注解设置为定义的属性,解析完成
放入容器中beanDefintionMap中
3.实例化非懒加载的单例bean
3.1对beanDefintionMap中的bean定义进行合并,放入合并后的bean定义容器中mergedBeanDefinitionMap
3.2.循环遍历合并后的bean定义容器,
根据bean定义中的scope属性查看是否是单例的bean,并查看是否是懒加载,实例化单例非懒加载的bean
实例化之后进行属性填充,
属性填充之后判断bean是否实现了Aware接口,调用Aware接口的实现方法
然后调用bean的初始化方法进行初始化
如果有切面,需要进行动态代理,生成代理bean
把生成的bean放入单例池。bean的实例化过程在spring中是调用bean的不同的后置处理器来完成的。
Spring AOP
切面(创建一个切面类@Aspect,切面类里面定义了很多切点)
切点:@PointCut(com.methd*) 连接点的集合
连接点 就是需要切入的某个方法
通知 切入的时机+切入的逻辑。@Before("myPointCut")
@Aspect
public class MyAspect {
//定义一个切点
@Pointcut("execution(* mjw.spring.aop.dao.*.*(..))")
public void myPointCut(){
}
//定义通知
@Before("myPointCut()")
public void beforeAdv(){
System.out.println("before 通知");
}
//也可以吧切点和通知合并配置
@Before("execution(* mjw.spring.aop.service.*.*(..))")
public void beforeAdv2(JoinPoint joinPoint){
System.out.println("before execution");
}
}
单例作用域的bean中引入原型作用域的Bean的问题
单例作用域的bean中引入原型作用域的Bean的问题
如果一个单例的bean中引用了一个多例的bean,这时候这个多例的bean只会被注入一次,所以达不到多例的效果了,如果想要达到多例的效果可以如下作用:
@Scope("prototype")
@Compent
Class Command{
}
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@Component
public class CommandManager implements ApplicationContextAware {
@AutoWared
private ApplicationContext applicationContext;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
protected Command createCommand() {
// 这样每次调用就可以创建一个新的实例,
//但是这种做法 代码侵入性太高
return this.applicationContext.getBean("command", Command.class);
}
public void setApplicationContext(
ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
@Scope("prototype")
@Component
Class Command{
}
package fiona.apple;
// Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
@Component
public abstract class CommandManager{
@LookUp
public abstract Command createCommand();
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
}
springMVC
1. 请求进来之后会进入到doDispatch()方法中。
2. 根据request从handlermappings循环获取handler,并构建成一个调用链对象
HandlerExecutionChain,调用链中包含handler对象以及拦截器。
注意:springMVC中生命一个controller有三种方式:@Controller注解\实现
Controller接口\实现HttpRequestHandler接口分别对应三种映射器来获取
handler对象。这三种方式@Contoller是把对象中的方法解析成一个个handler;
其余两种其实就是从Spring容器中获取真实的对象。
3. 根据request从匹配出适合的适配器,适配器也有三种分别对应不同的Controller类型,
4. Chain.applyPreHandle()按顺序调用拦截器
5. Ha.hand(hand) –通过适配器调用handle对应的方法。其中@Controller类型是通过反射调用,
期间会通过策略模式,根据不同类型的参数调用不同的参数解析器从request中解析参
数值,然后通过反射调用controller的方法;根据方法的返回值以及方法上有没有加@ResponseBody注解,
来判断是走视图解析器还是走消息转换器。
6. Chain.applyPostHandle()调用拦截器
7. 调用视图解析器渲染参数以及页面跳转。
手写springMVC
1.tomcat启动类
package com.luban.springmvc;
import com.luban.springmvc.servlet.DispatcherServlet;
import org.apache.catalina.Context;
import org.apache.catalina.core.StandardContext;
import org.apache.catalina.startup.Tomcat;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan("com.luban")
public class Start {
public static void main(String[] args) throws Exception {
Tomcat tomcat = new Tomcat();
tomcat.setPort(8080);
tomcat.addWebapp("/", "D:\\workspace\\springmvc\\src\\main\\webapp");
tomcat.start();
tomcat.getServer().await();
}
}
2.基于servlet3.0规范利用SPI机制web容器启动完毕之后加载DispatcherServlet
image.png
#com.luban.springmvc.init.Myinit
package com.luban.springmvc.init;
import com.luban.springmvc.Start;
import com.luban.springmvc.servlet.DispatcherServlet;
import org.apache.jasper.servlet.JspServlet;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;
import java.util.Set;
//SPI
public class Myinit implements ServletContainerInitializer{
@Override
public void onStartup(Set<Class<?>> c,ServletContext servletContext) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(Start.class);
DispatcherServlet servlet = new DispatcherServlet(ac);
ServletRegistration.Dynamic dy = servletContext.addServlet("app",servlet);
dy.setLoadOnStartup(1);
dy.addMapping("*.do");
/* JspServlet jspServlet = new JspServlet();
ServletRegistration.Dynamic dy1 = servletContext.addServlet("app1",jspServlet);
dy1.setLoadOnStartup(2);
dy1.addMapping("*.jsp");*/
}
}
3.DispatcherServlet
package com.luban.springmvc.servlet;
import com.luban.springmvc.init.handlerAdapter.HandlerAdapter;
import com.luban.springmvc.init.handlerMapping.HandlerMapping;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Map;
public class DispatcherServlet extends HttpServlet {
static Collection<HandlerAdapter> handlerAdapters ;
static Collection<HandlerMapping> handlerMappings ;
public DispatcherServlet() {
}
public DispatcherServlet(AnnotationConfigApplicationContext ac) {
//组件初始化
Map<String, HandlerMapping> handlerMappingMaps = ac.getBeansOfType(HandlerMapping.class);
handlerMappings = handlerMappingMaps.values();
Map<String, HandlerAdapter> handlerAdapterMaps = ac.getBeansOfType(HandlerAdapter.class);
handlerAdapters = handlerAdapterMaps.values();
}
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
Object handlerMapping = getHandlerMapping(req);
if(handlerMapping == null){
System.out.println("未匹配到handlerMapping");
return;
}
HandlerAdapter handlerAdapter = getHandlerAdapter(handlerMapping);
if(handlerAdapter == null){
System.out.println("未匹配到handlerAdapter");
return;
}
Object result = handlerAdapter.handle(req,resp,handlerMapping);
PrintWriter writer = resp.getWriter();
writer.println(result);
writer.flush();
writer.close();
}
protected Object getHandlerMapping(HttpServletRequest request) {
if (this.handlerMappings != null) {
for (HandlerMapping mapping : this.handlerMappings) {
Object handler = mapping.getHandlerMapping(request.getRequestURI());
if (handler != null) {
return handler;
}
}
}
return null;
}
protected HandlerAdapter getHandlerAdapter(Object handlerMapping) {
if (this.handlerAdapters != null) {
for (HandlerAdapter adapter : this.handlerAdapters) {
boolean flag = adapter.supports(handlerMapping);
if (flag) {
return adapter;
}
}
}
return null;
}
}
4.HandlerMapping
package com.luban.springmvc.init.handlerMapping;
public interface HandlerMapping {
Object getHandlerMapping(String requestURI);
}
package com.luban.springmvc.init.handlerMapping;
import com.luban.springmvc.controller.Controller;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
@Component
public class BeanNameHandlerMapping implements HandlerMapping,InstantiationAwareBeanPostProcessor {
public static Map<String, Controller> map = new HashMap<>();
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if(beanName.startsWith("/")){
map.put(beanName,(Controller)bean);
}
return true;
}
@Override
public Object getHandlerMapping(String requestURI) {
return map.get(requestURI);
}
}
package com.luban.springmvc.init.handlerMapping;
import com.luban.springmvc.annotation.RequestMapping;
import com.luban.springmvc.servlet.RequestMappingInfo;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
@Component
public class AnnotationHadlerMapping implements HandlerMapping,InstantiationAwareBeanPostProcessor {
public static Map<String,RequestMappingInfo> map = new HashMap<>();
@Override
//bean里面会有多个处理器
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
Method[] methods = bean.getClass().getDeclaredMethods();
for(Method method : methods){
RequestMappingInfo requestMappingInfo = createRequestMappingInfo(method,bean);
map.put(requestMappingInfo.getUri(),requestMappingInfo);
}
return true;
}
private RequestMappingInfo createRequestMappingInfo(Method method,Object bean) {
RequestMappingInfo requestMappingInfo = new RequestMappingInfo();
if(method.isAnnotationPresent(RequestMapping.class)){
requestMappingInfo.setMethod(method);
requestMappingInfo.setUri(method.getDeclaredAnnotation(RequestMapping.class).value());
requestMappingInfo.setObj(bean);
}
return requestMappingInfo;
}
@Override
public Object getHandlerMapping(String requestURI) {
return map.get(requestURI);
}
}
6.HandlerAdapter
package com.luban.springmvc.init.handlerAdapter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface HandlerAdapter {
//该方法判断handler是否是跟该适配器对应的Handler
public boolean supports(Object handler);
//执行handler的业务方法
public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler);
}
package com.luban.springmvc.init.handlerAdapter;
import com.alibaba.fastjson.JSON;
import com.luban.springmvc.annotation.RequestParam;
import com.luban.springmvc.annotation.ResponseBody;
import com.luban.springmvc.servlet.RequestMappingInfo;
import org.springframework.stereotype.Component;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Map;
@Component
public class AnnotationHandlerAdapter implements HandlerAdapter{
@Override
public boolean supports(Object handler) {
//判断是否是RequestMapping子类
return (handler instanceof RequestMappingInfo);
}
@Override
//参数绑定
public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler){
RequestMappingInfo requestMappingInfo = (RequestMappingInfo)handler;
Map<String, String[]> paramMap = request.getParameterMap();//请求携带的参数
Method method = requestMappingInfo.getMethod();//方法定义的参数
Parameter[] parameters = method.getParameters();
Object[] params = new Object[method.getParameterTypes().length];
for(int i=0; i<parameters.length; i++){
for(Map.Entry<String, String[]> entry : paramMap.entrySet()){
if(parameters[i].getAnnotation(RequestParam.class) != null && entry.getKey()!= null &&
entry.getKey().equals(parameters[i].getAnnotation(RequestParam.class).value())){
params[i] = entry.getValue()[0];
//jdk1.8实现反射获取方法名 1.8之前使用asm实现
}else if(entry.getKey().equals(parameters[i].getName())){
params[i] = entry.getValue()[0];
}
}
//传入request和response
if(ServletRequest.class.isAssignableFrom(parameters[i].getType())){
params[i] = request;
}else if(ServletResponse.class.isAssignableFrom(parameters[i].getType())){
params[i] = response;
}
}
try {
Object result = method.invoke(requestMappingInfo.getObj(),params);
if (result instanceof String) {
if ("forward".equals(((String) result).split(":")[0])) {
request.getRequestDispatcher(((String) result).split(":")[1]).forward(request, response);
} else {
response.sendRedirect(((String) result).split(":")[1]);
}
}else{
if(method.isAnnotationPresent(ResponseBody.class)){
return JSON.toJSONString(result);
}
}
return result;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
package com.luban.springmvc.init.handlerAdapter;
import com.luban.springmvc.controller.Controller;
import org.springframework.stereotype.Component;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Component
public class BeanNameHandlerAdapter implements HandlerAdapter{
@Override
// //判断hanlde是否适配当前适配器
public boolean supports(Object handler) {
//判断是否是RequestMapping子类
return (handler instanceof Controller);
}
@Override
public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler) {
return ((Controller)handler).handler(request, response);
}
}
7.RequestMappingInfo
package com.luban.springmvc.servlet;
import java.lang.reflect.Method;
public class RequestMappingInfo {
private Method method;
private String uri;
private Object obj;
public Object getObj() {
return obj;
}
public void setObj(Object obj) {
this.obj = obj;
}
public Method getMethod() {
return method;
}
public void setMethod(Method method) {
this.method = method;
}
public String getUri() {
return uri;
}
public void setUri(String uri) {
this.uri = uri;
}
}
7.Controller接口
package com.luban.springmvc.controller;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public interface Controller {
Object handler(HttpServletRequest request, HttpServletResponse response);
}
8.springMVC的controller类
public class HelloController {
@Autowired
HelloService service;
@RequestMapping("/test.do")
public String test(HttpServletRequest request, HttpServletResponse response,
@RequestParam("param") String param){
System.out.println("param:"+param);
service.test(param);
request.setAttribute("param",param);
return "forward:/test.jsp";
}
@RequestMapping("/test1.do")
@ResponseBody
public Map test1(String param){
Map map = new HashMap();
map.put("param",param);
return map;
}
@RequestMapping("/test2.do")
@ResponseBody
public User test2(String param){
User user = new User();
user.setName(param);
user.setAge(param);
return user;
}
}
@Component("/testController")//通过id定义url
public class TestController implements Controller{
@Override
public Object handler(HttpServletRequest request, HttpServletResponse response) {
System.out.println("TestController");
return null;
}
}
网友评论