SpringIOC
1.解析配置類Config.class思灰,獲取配置類上面@componetScan注解的值package
2.掃描package下的類雾袱,并把帶有@Compent注解的以及繼承自@Compent注解的類萧锉,解析成
beanDefintion(bean定義),解析類中定義的@Scope @Lazy 等注解設(shè)置為定義的屬性,解析完成
放入容器中beanDefintionMap中
3.實(shí)例化非懶加載的單例bean
3.1對(duì)beanDefintionMap中的bean定義進(jìn)行合并昼汗,放入合并后的bean定義容器中mergedBeanDefinitionMap
3.2.循環(huán)遍歷合并后的bean定義容器献宫,
根據(jù)bean定義中的scope屬性查看是否是單例的bean愿待,并查看是否是懶加載观谦,實(shí)例化單例非懶加載的bean
實(shí)例化之后進(jìn)行屬性填充拉盾,
屬性填充之后判斷bean是否實(shí)現(xiàn)了Aware接口,調(diào)用Aware接口的實(shí)現(xiàn)方法
然后調(diào)用bean的初始化方法進(jìn)行初始化
如果有切面豁状,需要進(jìn)行動(dòng)態(tài)代理捉偏,生成代理bean
把生成的bean放入單例池倒得。bean的實(shí)例化過(guò)程在spring中是調(diào)用bean的不同的后置處理器來(lái)完成的。
Spring AOP
切面(創(chuàng)建一個(gè)切面類@Aspect,切面類里面定義了很多切點(diǎn))
切點(diǎn):@PointCut(com.methd*) 連接點(diǎn)的集合
連接點(diǎn) 就是需要切入的某個(gè)方法
通知 切入的時(shí)機(jī)+切入的邏輯夭禽。@Before("myPointCut")
@Aspect
public class MyAspect {
//定義一個(gè)切點(diǎn)
@Pointcut("execution(* mjw.spring.aop.dao.*.*(..))")
public void myPointCut(){
}
//定義通知
@Before("myPointCut()")
public void beforeAdv(){
System.out.println("before 通知");
}
//也可以吧切點(diǎn)和通知合并配置
@Before("execution(* mjw.spring.aop.service.*.*(..))")
public void beforeAdv2(JoinPoint joinPoint){
System.out.println("before execution");
}
}
單例作用域的bean中引入原型作用域的Bean的問(wèn)題
單例作用域的bean中引入原型作用域的Bean的問(wèn)題
如果一個(gè)單例的bean中引用了一個(gè)多例的bean霞掺,這時(shí)候這個(gè)多例的bean只會(huì)被注入一次,所以達(dá)不到多例的效果了驻粟,如果想要達(dá)到多例的效果可以如下作用:
@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() {
// 這樣每次調(diào)用就可以創(chuàng)建一個(gè)新的實(shí)例,
//但是這種做法 代碼侵入性太高
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. 請(qǐng)求進(jìn)來(lái)之后會(huì)進(jìn)入到doDispatch()方法中根悼。
2. 根據(jù)request從handlermappings循環(huán)獲取handler,并構(gòu)建成一個(gè)調(diào)用鏈對(duì)象
HandlerExecutionChain,調(diào)用鏈中包含handler對(duì)象以及攔截器蜀撑。
注意:springMVC中生命一個(gè)controller有三種方式:@Controller注解\實(shí)現(xiàn)
Controller接口\實(shí)現(xiàn)HttpRequestHandler接口分別對(duì)應(yīng)三種映射器來(lái)獲取
handler對(duì)象挤巡。這三種方式@Contoller是把對(duì)象中的方法解析成一個(gè)個(gè)handler;
其余兩種其實(shí)就是從Spring容器中獲取真實(shí)的對(duì)象酷麦。
3. 根據(jù)request從匹配出適合的適配器矿卑,適配器也有三種分別對(duì)應(yīng)不同的Controller類型,
4. Chain.applyPreHandle()按順序調(diào)用攔截器
5. Ha.hand(hand) –通過(guò)適配器調(diào)用handle對(duì)應(yīng)的方法。其中@Controller類型是通過(guò)反射調(diào)用沃饶,
期間會(huì)通過(guò)策略模式母廷,根據(jù)不同類型的參數(shù)調(diào)用不同的參數(shù)解析器從request中解析參
數(shù)值,然后通過(guò)反射調(diào)用controller的方法;根據(jù)方法的返回值以及方法上有沒(méi)有加@ResponseBody注解糊肤,
來(lái)判斷是走視圖解析器還是走消息轉(zhuǎn)換器琴昆。
6. Chain.applyPostHandle()調(diào)用攔截器
7. 調(diào)用視圖解析器渲染參數(shù)以及頁(yè)面跳轉(zhuǎn)。
手寫springMVC
1.tomcat啟動(dòng)類
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規(guī)范利用SPI機(jī)制web容器啟動(dòng)完畢之后加載DispatcherServlet
#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里面會(huì)有多個(gè)處理器
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是否是跟該適配器對(duì)應(yīng)的Handler
public boolean supports(Object handler);
//執(zhí)行handler的業(yè)務(wù)方法
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
//參數(shù)綁定
public Object handle(HttpServletRequest request, HttpServletResponse response, Object handler){
RequestMappingInfo requestMappingInfo = (RequestMappingInfo)handler;
Map<String, String[]> paramMap = request.getParameterMap();//請(qǐng)求攜帶的參數(shù)
Method method = requestMappingInfo.getMethod();//方法定義的參數(shù)
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實(shí)現(xiàn)反射獲取方法名 1.8之前使用asm實(shí)現(xiàn)
}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是否適配當(dāng)前適配器
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")//通過(guò)id定義url
public class TestController implements Controller{
@Override
public Object handler(HttpServletRequest request, HttpServletResponse response) {
System.out.println("TestController");
return null;
}
}