有关springboot的一些理解

Explosion! / 2023-08-18 / 原文

springboot

概念

springboot是spring项目的脚手架,其能够快速构建spring项目,不再需要一些对应用程序的xml文件配置,其自带许多硬件设备的驱动。其核心是约定大于配置理念,即减少人为配置,尽量采用默认的配置即可。例如,不同于单独的springMVC,其默认配置了包括tomcat服务器,视图解析器等。springBoot专注于微服务方面的接口开发,和前端解耦。

spring boot默认的配置文件必须是,也只能是application.命名的yml文件或者properties文件,且唯一,默认只会去src-main-resources文件夹下去找application配置文件。

配置文件优先级 .properties > .yml >.yaml

spring boot注解代替 xml,是指使用 @Configuration 修饰配置类,在配置类中进行 bean 声明;注解 @ComponentScan 默认扫描当前修饰类的 package,将 @Component 修饰的类创建为 bean 放入容器中;注解 @PropertySource 用来引入 properties 资源文件,引入后应用中通过 @Value、@ConfigurationProperties 获取值;注解 @Import 用来引入 @Configuration,ImportSelector 或 ImportBeanDefinitionRegistrar 修饰的配置类;注解 @ImportResource 用来引入 xml 配置文件;

 

Spring的核心即为AOP和IOC

AOP

AOP (Aspect Orient Programming),直译过来就是 面向切面编程,AOP 是一种编程思想,是面向对象编程(OOP)的一种补充。面向切面编程,实现在不修改源代码的情况下给程序动态统一添加额外功能的一种技术。

应用场景:

  • 日志记录
  • 事务管理
  • 权限验证
  • 性能监测

核心概念:

  • Joinpoint(连接点):可以被拦截的点,spring中一般指被标注可拦截的方法。
  • Pointcut(切入点):属于Joinpoint,指要被拦截的点,即符合某种规则从Joinpoint筛选出的特定的连接点。
  • Advice(通知):拦截了Pointcut后在Pointcut上执行的增强处理,即需要额外执行的内容。
  • Target(目标):目标类,被代理的对象,真正执行的业务逻辑。
  • Weaving(织入):把切面应用到目标函数的过程。
  • Proxy(代理):代理的对象,即Target的代理对象。(详见超链接)
  • Aspect(切面):通常是一个类,定义了切入点和通知。

springAOP的通知有四种:

  • @Before(前置通知):在执行目标方法之前运行
  • @After(后置通知):在执行目标方法之后运行
  • @AfterReturning(返回通知):在目标方法正常返回后运行
  • @AfterThrowing(异常通知):在目标方法抛出异常后运行
  • @Around(环绕通知):在目标方法执行前后运行,该方法核心参数ProceedingJoinPoint,需要手动执行joinPoint.procced()。详见下例
   //切入点
    @Pointcut("@annotation(net.keysweb.annotation.GlobalInterceptor)")
    public void permissionPointcut(){};

    //通知
    @Around("permissionPointcut()")
    public Object interceptorDo(ProceedingJoinPoint joinPoint){
       try{
            //获得目标类
            Object target = joinPoint.getTarget();
            //获得目标参数
            Object[] args = joinPoint.getArgs();
            //获得连接点方法名
            String methodName = joinPoint.getSignature().getName();
            //获得连接点参数类列表
            Class<?>[] paramTypes = ((MethodSignature)joinPoint.getSignature()).getMethod().getParameterTypes();
            //获得连接点方法
            Method method = target.getClass().getMethod(methodName,paramTypes);
            ...
            //放行
            Object pointResult = joinPoint.proceed();
            ...
        }catch(...){
            ...
        }
};

IOC

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法

没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,所谓控制反转就是:获得依赖对象的方式反转了。

IOC容器

SpringIOC的实现是用SpringIOC容器来管理实例化对象,SpringIOC容器是一个管理Bean的容器,在Spring的定义里,所有IoC容器都要实现接口BeanFactory

package org.springframework.beans.factory;

import org.springframework.beans.BeansException;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

public interface BeanFactory {
    //前缀
    String FACTORY_BEAN_PREFIX = "&";
    
    //多个getBean方法
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
    
    //是否包含Bean
    boolean containsBean(String var1);
    //Bean是否为单例
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
    //Bean是否为原型
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
    //是否类型匹配
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;
    //获取Bean的类型
    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;

    @Nullable
    Class<?> getType(String var1, boolean var2) throws NoSuchBeanDefinitionException;
    //获取Bean的别名
    String[] getAliases(String var1);
}
View Code

源码里有多个getBean方法,有按类型获取Bean的,有按名称获取Bean的。需注意,Spring默认为单例Bean。

具体注入过程详见下文springboot的启动过程

使用@Autowired会根据属性找到对应的Bean并注入。但是当我们需要注入的是接口类,且该接口类有多个实现类时,就会产生歧义

@Primary告诉IoC容器,当有多个同类型的Bean时,优先使用我注入

@Primary可能修饰多个类,此时就不能单用@Primary来消除歧义,@Qualifier的配置项value需要一个字符串定义,这样Autowired就会通过类型和名称一起找到Bean

 

 

SpringBoot启动过程

SpringBoot启动类如下:

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

注意,虽然启动类是DemoApplication,但是SpringApplication.run传入的配置类可以不是DemoApplication,run传入的配置类决定了springboot的默认扫描路径,即该配置类路径下的所有包。@SpringBootApplication注解的核心是 @Configuration、@EnableAutoConfiguration、@ComponentScan三个注解,

其中

  • @Configuration:代表这是一个Java配置类
  • @ComponentScan:扫描被@Component (@Service、@Controller、@Mapper等)注解的 Bean,该扫描路径即刚才提到的传入的配置类的路径,因此我们只需在项目中对应的类上加上  @Service、@Controller、@Mapper等即可将其交给IoC容器管理
  • @EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
    excludeFilters = {@Filter(
    type = FilterType.CUSTOM,
    classes = {TypeExcludeFilter.class}
), @Filter(
    type = FilterType.CUSTOM,
    classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {

    //通过类型排除自动装配类
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    Class<?>[] exclude() default {};

    //通过名称排除自动装配类
    @AliasFor(
        annotation = EnableAutoConfiguration.class
    )
    String[] excludeName() default {};
    //定义扫描包
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackages"
    )
    String[] scanBasePackages() default {};
    //定义被扫描的类
    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "basePackageClasses"
    )
    Class<?>[] scanBasePackageClasses() default {};

    @AliasFor(
        annotation = ComponentScan.class,
        attribute = "nameGenerator"
    )
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;

    @AliasFor(
        annotation = Configuration.class
    )
    boolean proxyBeanMethods() default true;
}
View Code

 

在run方法中springboot执行了许多操作,包括启动web服务器(默认为tomcat)并设置springmvc等操作。期间对于所有jar包中的自带配置类(AutoConfig),SpringBoot会去扫描引入的jar包中的META-INFO文件中的spring.factories文件(在该文件中,会以key-value的形式去标出配置类文件的引用路径)和spring-autoconfigure-metadata.properties文件(该文件以key-value的形式去标出核心配置类,以方便springboot快速判断这些类是否能被正确加载,从而去成功引入对应的配置类),springboot通过类加载器(classLoader)去将这些路径以map的方式储存并使用,从而达到自动配置的效果。

 

 

 

 

springmvc

MVC

MVC是模型(Model)、视图(View)、控制器(Controller)的简写,是一种软件设计规范。

  • 是将业务逻辑、数据、显示分离的方法来组织代码。
  • MVC主要作用是降低了视图与业务逻辑间的双向偶合。
  • MVC不是一种设计模式,MVC是一种架构模式。当然不同的MVC存在差异。

​ Model(模型):数据模型,提供要展示的数据,因此包含数据和行为,可以认为是领域模型或JavaBean组件(包含数据和行为),不过现在一般都分离开来:Value Object(数据Dao) 和 服务层(行为Service)。也就是模型提供了模型数据查询和模型数据的状态更新等功能,包括数据和业务。

​ View(视图):负责进行模型的展示,一般就是我们见到的用户界面,客户想看到的东西。

​ Controller(控制器):接收用户请求,委托给模型进行处理(状态改变),处理完毕后把返回的模型数据返回给视图,由视图负责展示。也就是说控制器做了个调度员的工作。

概念

Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。SpringMVC , 简单 , 便捷 , 易学 , 天生和Spring无缝集成(使用SpringIoC和Aop) , 使用约定优于配置 . 能够进行简单的junit测试 . 支持Restful风格 .异常处理 , 本地化 , 国际化 , 数据验证 , 类型转换 , 拦截器 等等…

 

 

本文部分为个人理解,仅供参考

参考文章:https://blog.csdn.net/qq_38939822/article/details/124258258

     https://blog.csdn.net/cyx_159/article/details/131516933