文章目录
一、IOC容器的构建
1.MySSM的class diagram和原理
- 其中BeanFactory中主要提供了getBean(),由实现类ClassPathXmlApplicationContext进行具体动能的实现。**内部原理是:**通过DOM技术,利用抽象类DocumentBuilderFactory生成DocumentBuilder,用其parse()进行xml文件的读取。
- 然后,依次将bean节点中对应的id和class元素通过反射生成bean对象(基于无参构造),并保存到beanMap中。
- 后续即可根据key值(也就是id)从beanMap中获取bean对象。
2.SSM的class diagram和原理
- 几个值得关注的类和接口的简介如下:
- 其中beanFactory中也定义了很多重载的getBean方法,底层是通过反射加工厂模式进行的bean对象的构建(仍基于无参构造)。
- 基于注解管理bean时,主要用@Component,@Controller,@Service,@Repository,而且需要在ApplicationContext.xml中开启扫描注解的功能。springMVC中扫描Controller组件,spring中扫描其他组件。
<!--扫描组件-->
<context:component-scan base-package="包名">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:component-scan>
两者的相同点
- 实例化bean对象时,MySSM使用的是饿汉式单例模式,SSM中当bean的scope属性为singleton时用的也是饿 汉式单例模式
两者的区别:
- MySSM中只能通过id进行bean的获取(整个bean对象的构建是在ClassPathXmlApplicationContext类中进行的,getBean()的调用是在DispatcherServlet类中,利用*.do即servletPath进行字符串截取,以获得对应的Contraller的id)
- SSM中可以通过bean的id也就是name和class也就是type进行getBean(),而且可以同时根据name和type进行bean获取(方法的重载),甚至可以通过实现类的接口类型进行获取(对象instanceof指定的类型,为true就可以),使用的比较多的就是通过type进行bean的获取。
- MySSM中没有导入spring依赖,所以bean只能通过xml配置方式交给手写的ioc容器管理;SSM中可以通过xml和注解的方式将bean交给ioc管理,但是使用注解只能把自己写的类交给spring管理,第三方jar中的类还是得用xml的方式。
二、DI的实现原理
1.MySSM
同样利用DOM技术,通过将bean中的子节点property的两个元素name和ref提取出来,在依次给beanMap中的对象进行依赖注入,也就是给属性进行赋值。这里值得注意的是,MySSM中只用到了类类型属性,所以只有name\ref的形式,没有name\value(用于Integer,Double,String等字面量类型)的形式,而且此时的依赖注入也是根据field的set方法进行注入的,此时fiele在类中可以没有set()方法。
2.SSM
xml中依赖注入主要用的是setter注入(用的比较多)和有参构造器注入
自动装配:(通过AutoWire根据一定的策略为属性自动匹配某个bean,只能为类类型或接口类型的属性赋值)
- xml中可以用bean的autowire元素进行策略的指定,默认为default也就是no,还有byType和byName,byType和byName不行的时候就会使用no策略,会报空指针,但是该元素的效果会对整个bean的类或接口类型的属性进行自动装配,不太实用。
- 利用注解@AutoWired进行自动装配时,可以标在成员变量、set()、有参构造上,策略默认优先byType,byType找不到唯一一个bean就用byName,byName找不到就会报有多个同类型的bean。注解只能用于自己写的类(因为第三方类在jar包中,无法修改代码),且也只能根据指定的策略为类类型或接口类型的属性赋值。
- 一种特殊情况:开发中,实现类需要更新,此时不会在原有的实现类中更新,会重新写一个实现类,如果此时为接口自动装配,就会产生问题。解决方案:1.把旧的bean删掉;2.xml中用byName策略;3.基于注解时加上@Autowired(换行)@Qualifier(“***”)//可以通过此注解进行绑定,并不需要修改属性名称
也就是说SSM中的字面量属性只能通过xml进行依赖注入,不能自动装配。
两者的相同点
两者的区别:
- MySSM中的依赖注入不是必须要有成员变量的set(),而SSM中使用setter注入就必须要有对应的set(),有参构造器注入和基于注解的自动装配不需要set()
关于生命周期
- MySSM中bean的生命周期:实例化,依赖注入(前两步是由ClassPathXmlApplicationContext完成的),ioc容器关闭时销毁。
- SSM中bean的生命周期:实例化,依赖注入,初始化之前的操作,初始化,初始化之后的操作,ioc容器关闭时销毁(当bean的scope属性为prototype时,销毁就不由ioc容器管理,即ConfigurableApplicationContext中close()执行时,不会执行bean的destory-method对应的方法)。
- SSM中ioc容器中管理了实现BeanPostProcesser接口的类,才会执行初始化之前的操作和初始化之后的操作。而且这个操作是针对所有bean初始化有效。
三、通过上述的原理得到的一些关于构建项目的注意点
1.无参构造
- 没有无参构造会报错:java.lang.NoSuchMethodException:***类.()
2.属性和成员变量的区别(setter方法)
- 有set()方法的成员变量才叫属性,不能混为一谈。
四、利用中央控制器DispatcherServlet进行统一请求处理的异同
1.MySSM
- 实现思想:将DispatcherServlet的url-partten设置为拦截所有请求,在请求路径中加上*.do用来表示使用哪个Controller,在请求参数中通过operate的值确定是哪个方法。Controller的实现类直接在IOC容器(Map集合)中得到,方法通过方法名反射得到,再根据形参列表从请求参数中一一获取(值得注意的是Request和Response不在参数列表中,可以直接传参)。最后进行方法的调用。
- 请求处理部分:方法执行的返回值统一为字符串,请求转发直接返回目标地址,DispatcherServlet会将其通过Thymeleaf视图解析器进行处理转发;重定向的返回值在目标地址前加上"redirect:“,DisPatcherServlet会识别该前缀,将其通过Response.sendRedirect()进行重定向;json格式的数据在返回的字符串前加上"json:”,DispatcherServlet识别该前缀,通过Response.getWriter().writer()将其返回到网页。如果返回值是空字符串,就不做处理。
- 其中json格式的数据和Java对象之间使用GSON提供的工具类进行转换,主要用于异步请求。
2.SSM
- 实现思想:同样是在web.xml中将springMVC提供的DispatcherServlet的url-partten设置为所有路径(此处注意:/代表是除jsp的所有路径,/*代表包含jsp的所有路径)。
- 返回值也都是字符串。请求转发直接返回目标地址,在springMVC中配置了thymeleaf视图解析器。重定向的返回值也是在目标地址前加上"redirect:",DisPatcherServlet会识别该前缀;想返回json格式的数据,直接在方法上加上注解@ResponseBody,springMVC会自动将返回的Java对象转化为json数据,底层使用的jackson提供的方法。
- 底层的逻辑都是使用Model And View,根据返回的字符串生成对应的InternalResourceView、ThymeleafView、RedirectView
五、两个框架中在web.xml文件中配置的一些基本组件
1.MySSM
MySSM在web.xml中配置了四样基本的组件:(因为都是自己写的类,所以可以用注解@Servlet、@Filter、@Listener进行配置)
- 编码过滤器,用于解决POST方法返回的请求参数乱码的问题
- 事务过滤器OpenSessionInViewFilter,用于处理事务
- 中央控制器DispatcherServlet,用于处理请求和响应
- ContextLoaderListener监听器,用于加载applicatonContext.xml文件,用于在Tomcat启动时就生成IOC容器
2.SSM
SSM在web.xml中配置了五样基本的组件:
- 编码过滤器,用于解决POST方法返回的请求参数乱码的问题
- 请求方法过滤器,提供了put和delete方法,主要用于RESTFUL处理请求的风格
其中put和delete方法使用的要求:1.必须使用form表单,method为post;2.必须有一个hidden类型的input,name=“_method”,value值为真正的方法。 - 中央控制器DispatcherServlet,用于处理请求和响应,并在init-param中加载springMVC的配置文件
- ContextLoaderListener监听器,用于加载spring的配置文件
- 上下文参数context-param,用于标识spring配置文件的类路径