IT总结 | Spring、SpringMVC、SpringBoot、SpringCloud之间的关系

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通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。

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框架的单体微服务;为微服务体系开发中的架构问题,提供了一整套的解决方案。

你可能感兴趣的:(IT总结 | Spring、SpringMVC、SpringBoot、SpringCloud之间的关系)