Spring与SpringMVC
Spring是一个一站式的框架,提供了表现层(SpringMVC/Struts)到业务层(Spring)再到数据层(Hibernate/Mybatis)都提供了多种配置解决方案;Spring的两大核心IOC(控制反转)和AOP(面向切面编程)更是给我们的程序解耦和代码的简介提供了支持。
即Spring在JavaEE的三层架构[表现层(Web层)、业务逻辑层(Service层)、数据访问层(DAO层)]中,每一层均提供了不同的解决技术。如下:
• 表现层(Web层):Spring MVC
• 业务逻辑层(Service层):Spring的IoC
• 数据访问层(DAO层):Spring的jdbcTemplate
Spring是IOC和AOP的容器框架,SpringMVC是基于Spring功能之上添加的Web框架,想用SpringMVC必须先依赖Spring。
Spring MVC通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。主要针对的是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。
-
SpringMVC的执行流程
1、 用户发送请求至前端控制器DispatcherServlet;
2、DispatcherServlet收到请求调用HandlerMapping处理器映射器;
3、处理器映射器根据请求url找到具体的处理器,生成处理器对象及处理器拦截器(如果有则生成)一并返回给DispatcherServlet;
4、DispatcherServlet通过HandlerAdapter处理器适配器调用处理器,执行处理器(Controller,也叫后端控制器);
5、Controller执行完成返回ModelAndView,并返回给HandlerAdapter,HandlerAdapter将结果返回给DispatcherServlet;
6、DispatcherServlet将ModelAndView传给ViewReslover视图解析器,ViewReslover解析后返回具体View给DispatcherServlet;
7、DispatcherServlet对View进行渲染视图(即将模型数据填充至视图中)后返回给给客户
-
Spring的优点
1、降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2、容器提供单例模式支持
在Spring中,bean可以被定义为两种模式:prototype(多例)和singleton(单例), 默认是单例模式。
2.1、singleton(单例):只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一的实例。
2.2、prototype(多例):对这个bean的每次请求都会创建一个新的bean实例,类似于new。
3、容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
4、Spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
5、spring的DI机制降低了业务对象替换的复杂性
-
什么是DI机制?
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。
但在Spring中创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由Spring来完成,然后注入调用者因此也称为依赖注入。
Spring以动态灵活的方式来管理对象 , 注入的两种方式,设置注入和构造注入。
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。
-
Spring的IOC
Spring IOC(控制反转,也可以称为依赖倒置),将传统的对象创建流程转变为交由Spring框架进行创建和管理。Spring IOC操作分为:IOC配置文件方式和IOC的注解方式。
-
Spring的AOP
面向切面编程(AOP)是对面向对象编程(OOP)的补充,面向切面编程在Spring中主要表现为两个方面:
1、面向切面编程提供声明式事务管理
2、Spring支持用户自定义的切面
AOP采取横向抽取机制,取代了传统纵向继承体系重复性代码,例如:事务管理、性能监视、安全检查、缓存 、日志等。
AOP实现原理:
1、AOP底层将采用代理机制进行实现。
2、接口 + 实现类 :Spring采用 JDK的动态代理Proxy。
3、实现类:Spring采用 Cglib字节码增强。
JDK动态代理
public static UserService createService(){
//1 目标类
final UserService userService = new UserServiceImpl();
//2切面类
final MyAspect aspect = new MyAspect();
/* 3 代理类:将目标类(切入点)和 切面类(通知) 结合 --> 切面
* Proxy.newProxyInstance
* 参数1:loader ,类加载器,动态代理类 运行时创建,任何类都需要类加载器将其加载到内存。
* 一般情况:当前类.class.getClassLoader();
* 目标类实例.getClass().get...
* 参数2:Class[] interfaces 代理类需要实现的所有接口
* 方式1:目标类实例.getClass().getInterfaces() ;注意:只能获得自己接口,不能获得父元素接口
* 方式2:new Class[]{UserService.class}
* 例如:jdbc 驱动 --> DriverManager 获得接口 Connection
* 参数3:InvocationHandler 处理类,接口,必须进行实现类,一般采用匿名内部
* 提供 invoke 方法,代理类的每一个方法执行时,都将调用一次invoke
* 参数31:Object proxy :代理对象
* 参数32:Method method : 代理对象当前执行的方法的描述对象(反射)
* 执行方法名:method.getName()
* 执行方法:method.invoke(对象,实际参数)
* 参数33:Object[] args :方法实际参数
*
*/
UserService proxyService = (UserService)Proxy.newProxyInstance(
MyBeanFactory.class.getClassLoader(),
userService.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前执行
aspect .before();
//执行目标类的方法
Object obj = method.invoke(userService, args);
//后执行
aspect .after();
return obj;
}
});
return proxyService;
}
Spring的CGLIB字节码增强
public static UserServiceImpl createService(){
//1 目标类
final UserServiceImpl userService = new UserServiceImpl();
//2切面类
final MyAspect myAspect = new MyAspect();
// 3.代理类 ,采用cglib,底层创建目标类的子类
//3.1 核心类
Enhancer enhancer = new Enhancer();
//3.2 确定父类
enhancer.setSuperclass(userService.getClass());
/* 3.3 设置回调函数 , MethodInterceptor接口 等效 jdk InvocationHandler接口
* intercept() 等效 jdk invoke()
* 参数1、参数2、参数3:以invoke一样
* 参数4:methodProxy 方法的代理
*/
enhancer.setCallback(new MethodInterceptor(){
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前执行
myAspect.before();
//执行目标类的方法
Object obj = method.invoke(userService, args);
// * 执行代理类的父类 ,执行目标类 (目标类和代理类 父子关系)
methodProxy.invokeSuper(proxy, args);
//后执行
myAspect.after();
return obj;
}
});
//3.4 创建代理
UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService;
}
注解方式
/*
* 声明一个切面
* 自动注解AOP
*/
@Aspect
@Component(value="aopDemoOrder")
public class AopDemoOrder {
// 配置切点 及要传的参数
@Pointcut("execution(* com.spring.aop.OrderService.GetDemoOrder(..)) && args(id)")
public void pointCut(int id)
{
}
// 配置连接点 方法开始执行前通知
@Before("pointCut(id)")
public void beforeLog(int id) {
System.out.println("开始执行前置通知 日志记录:"+id);
}
// 方法执行完后通知
@After("pointCut(id)")
public void afterLog(int id) {
System.out.println("方法执行完后置通知 日志记录:"+id);
}
// 执行成功后通知
@AfterReturning("pointCut(id)")
public void afterReturningLog(int id) {
System.out.println("方法成功执行后通知 日志记录:"+id);
}
// 抛出异常后通知
@AfterThrowing("pointCut(id)")
public void afterThrowingLog(int id) {
System.out.println("方法抛出异常后通知 日志记录"+id);
}
// 环绕通知
@Around("pointCut(id)")
public Object aroundLog(ProceedingJoinPoint joinpoint, int id) {
Object result = null;
try {
System.out.println("环绕通知开始 日志记录"+id);
long start = System.currentTimeMillis();
//有返回参数 则需返回值
result = joinpoint.proceed();
} catch (Throwable t) {
System.out.println("出现错误");
}
return result;
}
}
-
BeanFactory与FactoryBean
1、BeanFactory是个Factory,也就是IOC容器或对象工厂。在Spring中,所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的。
2、FactoryBean是Spring通过反射机制利用
SpringBoot与SpringCloud
Spring Boot,看名字就知道是Spring的一套快速配置脚手架,可以基于Spring Boot快速开发单个微服务。
Spring Cloud基于Spring Boot,为微服务体系开发中的架构问题,提供了一整套的解决方案——服务注册与发现,服务消费,服务保护与熔断,网关,分布式调用追踪,分布式配置管理等。
Spring Boot可以离开Spring Cloud独立使用开发项目,但是Spring Cloud离不开Spring Boot,属于依赖的关系。
总结
1、 Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring的IOC、AOP等, IOC提供了依赖注入的容器, AOP解决了面向横切面编程,然后在此两者的基础上实现了其他延伸产品的高级功能;
2、 SpringMVC是基于Servlet 的一个MVC框架主要解决Web开发的问题,因为Spring的配置非常复杂,各种XML、JavaConfig、servlet处理起来比较繁琐;
3、为了简化开发者的使用,推出了Spring Boot框架默认优于配置,简化了SpringMVC的配置流程;但区别于SpringBoot专注于微服务方面的接口开发,和前端解耦,虽然SpringBoot也可以做成SpringMVC前后台一起开发,但是这就有点不符合SpringBoot框架的初衷了;
4.、SpringCloud关注的是全局微服务的整合和管理,相当于管理多个SpringBoot框架的单体微服务;为微服务体系开发中的架构问题,提供了一整套的解决方案。