一 Spring 简介
Spring是一个
轻量级的控制反转和面向切面的容器
框架,用来解决企业项目开发的复杂度问题——解耦Spring两大核心思想:IoC和AOP
IoC
AOP
-
轻量级:体积小,对项目代码没有侵入性
-
控制反转:IoC(Inverse of Control),把创建对象、给对象属性赋值的工作交由Spring完成;Spring在通过反射创建对象的同时可以给属性赋值(DI:依赖注入)
-
面向切面:AOP(Aspect Oriented Programming)面向切面编程,可以在不改变原有业务代码的前提下进行业务的增强(原理:动态代理)
-
容器:实例对象,Spring不仅可以创建对象,还可以对创建的对象进行管理。
Spring架构图
1.1 控制反转
IoC对编程带来的最大改变不是从代码上,而是从思想上,发生了“主从换位”的变化。应用程序原本是老大,要获取什么资源都是主动出击,但是在IoC/DI思想中,应用程序就变成被动的了,被动的等待IoC容器来创建并注入它所需要的资源了。
IoC很好的体现了面向对象设计法则之一—— 好莱坞法则:“别找我们,我们找你”;即由IoC容器帮对象找相应的依赖对象并注入,而不是由对象主动去找。
依赖注入(DI Dependency Injection)——依赖Spring容器工厂给创建的对象的属性注入值
DI注入的几种方式:
-
set方法注入:通过反射调用属性的set方法进行属性赋值
-
需要提供无参构造器
-
需要提供属性的set方法
public class Id { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } <bean id="id" class="com.id "> <property name="id" value="123"></property> </bean>
-
-
构造器注入:通过反射调用有参构造器创建对象并给属性赋值
-
需要提供有参构造器
-
constructor-arg标签设置参数要与构造器参数顺序一致,如果不一致需要通过index属性指定赋值给第一个参数(从0开始)
-
/*带参数,方便利用构造器进行注入*/
public CatDaoImpl(String message){
this. message = message;
}
<bean id="CatDaoImpl" class="com.CatDaoImpl">
<constructor-arg value=" message "></constructor-arg>
</bean>
3 接口注入:几乎不用
4 静态工厂注入
静态工厂顾名思义,就是通过调用静态工厂的方法来获取自己需要的对象,为了让 spring 管理所 有对象,我们不能直接通过"工程类.静态方法()"来获取对象,而是依然通过 spring 注入的形式获 取:
public class DaoFactory { //静态工厂
public static final FactoryDao getStaticFactoryDaoImpl(){
return new StaticFacotryDaoImpl();
}
}
public class SpringAction {
private FactoryDao staticFactoryDao; //注入对象
//注入对象的 set 方法
public void setStaticFactoryDao(FactoryDao staticFactoryDao) {
this.staticFactoryDao = staticFactoryDao;
}
}
//factory-method="getStaticFactoryDaoImpl"指定调用哪个工厂方法
<bean name="springAction" class=" SpringAction" >
<!--使用静态工厂的方法注入对象,对应下面的配置文件-->
<property name="staticFactoryDao" ref="staticFactoryDao"></property>
</bean>
<!--此处获取对象的方式是从工厂类中获取静态方法-->
<bean name="staticFactoryDao" class="DaoFactory"
factory-method="getStaticFactoryDaoImpl"></bean>
5 实例工厂
实例工厂的意思是获取对象实例的方法不是静态的,所以你需要首先 new 工厂类,再调用普通的 实例方法 :
public class DaoFactory { //实例工厂
public FactoryDao getFactoryDaoImpl(){
return new FactoryDaoImpl();
13/04/2018 Page 128 of 283
}
}
public class SpringAction {
private FactoryDao factoryDao; //注入对象
public void setFactoryDao(FactoryDao factoryDao) {
this.factoryDao = factoryDao;
}
}
<bean name="springAction" class="SpringAction">
<!--使用实例工厂的方法注入对象,对应下面的配置文件-->
<property name="factoryDao" ref="factoryDao"></property>
</bean>
<!--此处获取对象的方式是从工厂类中获取实例方法-->
<bean name="daoFactory" class="com.DaoFactory"></bean>
<bean name="factoryDao" factory-bean="daoFactory"
factory-method="getFactoryDaoImpl"></bean>
自动装配
自动装配有五种自动装配的方式,可以用来指导 Spring 容器用自动装配方式来进行依赖注入。
1. no:默认的方式是不进行自动装配,通过显式设置 ref 属性来进行装配。
2. byName:通过参数名 自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被设 置成 byname,之后容器试图匹配、装配和该 bean 的属性具有相同名字的 bean。
3. byType:通过参数类型自动装配,Spring 容器在配置文件中发现 bean 的 autowire 属性被 设置成 byType,之后容器试图匹配、装配和该 bean 的属性具有相同类型的 bean。如果有多 个 bean 符合条件,则抛出错误。
4. constructor:这个方式类似于 byType, 但是要提供给构造器参数,如果没有确定的带参数 的构造器参数类型,将会抛出异常。
5. autodetect:首先尝试使用 constructor 来自动装配,如果无法工作,则使用 byType 方式。
1.2 面向切面
AOP (Aspect Oriented Programming)面向切面编程,是一种利用“横切”的技术(底层实现就是动态代理),对原有的业务进行拦截,并且可以在拦截的横切面上添加特定的业务逻辑,从而实现对原有业务的增强。
Spring 提供了两种方式来生成代理对象: JDKProxy 和 Cglib,具体使用哪种方式生成由 AopProxyFactory 根据 AdvisedSupport 对象的配置来决定。默认的策略是如果目标类是接口, 则使用 JDK 动态代理技术,否则使用 Cglib 来生成代理。
/**
*
* JDK动态代理类创建规则:
* 1.实现InvocationHandler接口,同时实现invoke方法
* 2.在类中定义一个Object类型变量obj,提供有参构造器,用于将被代理对象传递进来
* 3.定义一个getProxy方法返回代理对象
*/
public class JDKDynamicProxy implements InvocationHandler {
//被代理对象
private Object obj;
//有参构造器
public JDKDynamicProxy(Object obj) {
this.obj = obj;
}
public Object getProxy(){
ClassLoader classLoader = obj.getClass().getClassLoader();
Class<?>[] interfaces = obj.getClass().getInterfaces();
Object proxy = Proxy.newProxyInstance(classLoader,interfaces,this);
return proxy;
}
/**
* 通过此JDK动态代理类产生的代理对象,调用方法时都会执行当前invoke方法
* @param proxy
* @param method 指代的是通过代理对象调用的方法(insert)
* @param args 指代的是通过被代理对象调用的方法的参数 (insert方法的参数)
* @return
* @throws Throwable
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("=============start");
Object r = method.invoke(obj, args); //执行insert方法
System.out.println("=============commit");
return r;
}
}
/**
* CGLib动态代理类创建规则
* 1.实现MethodInterceptor接口,实现intercept方法
* 2.在类中定义一个Object类型变量obj,提供有参构造器,用于将被代理对象传递进来
* 3.定义一个getProxy方法返回代理对象
*
*/
public class CGLibDynamicProxy implements MethodInterceptor {
private Object obj;
public CGLibDynamicProxy(Object obj) {
this.obj = obj;
}
public Object getProxy(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
//如果使用此动态代理类产生的代理对象调用方法,则回调此类中intercept
enhancer.setCallback(this);
Object proxy = enhancer.create();
return proxy;
}
/**
* 使用此动态代理类产生的代理对象调用方法时,并不会执行被调用的方法
* 而是执行此intercept方法,被调用的方法作为参数传递进来
* @param o
* @param method 被调用的方法
* @param objects 被调用的方法的参数
* @param methodProxy
* @return
* @throws Throwable
*/
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(">>>>>>>>>>>>>>start");
Object r = method.invoke(obj, objects);
System.out.println(">>>>>>>>>>>>>>commit");
return r;
}
}
二 Spring Mvc 概述
Spring MVC是由Spring官方提供的基于MVC设计理念,通过对Servlet封装实现MVC控制的web组件(框架)
流程分析:
①前端放松请求被前端控制器DispatcherServlet组件拦截
②前端控制器调用处理器映射HandlerMapping组件对请求URL进行解析,解析之后返回调用链给前端控制器
③前端控制器调用处理器适配器HandlerAdapter组件处理调用链
④处理器适配器基于反射通过适配器模式调用`控制器/处理器`处理用户请求,并返回数据及视图(ModelAndView,String)信息给处理器适配器
⑤处理器适配器封装视图及数据到ModelAndView对象,将ModelAndView对象返回给前端控制器
⑥前端控制器调用视图解析器ViewResolver组件进行解析(分离视图资源和数据资源),将解析结果返回给前端控制器
⑦前端控制器调用视图View组件对视图和数据进行渲染,将渲染结果(html)返回给前端控制器
⑧前端控制器将渲染响应给用户浏览器
三 Spring boot
概述:
Spring Boot 是由 Pivotal 团队提供的全新框架,其设计目的是用来简化新 Spring 应用的初始搭 建以及开发过程。该框架使用了特定的方式来进行配置,从而使开发人员不再需要定义样板化的 配置。通过这种方式,Spring Boot 致力于在蓬勃发展的快速应用开发领域(rapid application development)成为领导者。
特点:
1. 创建独立的 Spring 应用程序
2. 嵌入的 Tomcat,无需部署 WAR 文件
3. 简化 Maven 配置
4. 自动配置 Spring
5. 提供生产就绪型功能,如指标,健康检查和外部配置
6. 绝对没有代码生成和对 XML 没有要求配置
Spring版本发展
-
Spring 1.x
-
所有的spring配置只能通过xml方式完成 (<bean id="" class=""/>)
-
-
Spring 2.x
-
自JDK1.5开始支持注解,Spring从2.x开始支持使用注解
-
企业开发中到底是使用注解配置还是xml配置?
-
对于基础配置、引用第三方依赖中的配置需要使用XML配置完成
-
对于项目业务开发(例如:控制器类、业务类)使用注解
-
-
-
Spring 3.x
-
开始支持基于Java类的配置(注解)
-
自3.x版本开始:xml、注解、Java配置
-
java.util.Date com.qfedu.entity.Student
3.4.2 XML配置
<bean id="date" class="java.util.Date"></bean> <bean id="stu" class="com.qfedu.entity.Student"></bean>
3.4.3 注解配置
@Component public class Student{ }
3.4.4 Java配置
@Configuration public class MyConfig{ @Bean public Date getDate(){ return new Date(); } @Bean public Student getStudent(){ return new Student(); } }
四 其它
4.1 Spring,Spring MVC,Spring boot常用注解
Spring:
Spring MVC:
Spring boot:
@SpringBootApplication
实际指代的是一组注解,启动类注解
-
@ComponentScan注解,声明Spring容器的组件加载范围——启动类所在的包
-
@EnableAutoConfiguration注解,声明开启SpringBoot的自动配置
-
@SpringBootConfiguration注解,声明启动类同时为Spring的配置类(在配置类中定义方法,在方法上添加@Bean注解,就可以将方法返回的对象存放到Spring容器)
2 Spring boot启动及自动装配原理
自动配置原理:SpringBoot的自动配置就是通过自定义实现ImportSelector接口,然后通过SpringFactoriesLoader扫描autoconfigure包下的META-INF/spring.factories中所有路径下的类,并通过反射实例化成一个个的配置类并注入到Spring容器中,从而实现了自动装配,
引用一下大佬的文章
3 Spring boot 中的starter
可以看成是对依赖的一种合成,starter会把一个或者一套功能相关的依赖导入进来,避免自己去导入依赖包以及解决依赖冲突问题.
4 Spring boot配置拦截器
创建拦截器-实现 HandlerInterceptor接口
配置拦截器路径-实现WebMvcConfigurer接口
4 springboot 全局异常处理
常用的有
使用注解@ExeceptionHandler
使用HandlerExceptionResolver自定义全局处理异常类
总结:后续继续更新,脑子一团糟...