4

Spring框架学习记录

 2 years ago
source link: https://duzhi5368.github.io/2020/04/spring%E6%A1%86%E6%9E%B6%E5%AD%A6%E4%B9%A0%E8%AE%B0%E5%BD%95/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

近来在做web开发,从spring开始做一些简单的学习。

下面是一些基本的spring概念,在学习时逐步记录下来。

Spring框架学习记录

Spring核心思想

  • IOC: inversion of control 控制反转。

    • 把创建对象new,对象依赖关联关系交给容器去处理,目的解耦合。
    • 我们常见的bean对象,就是交给spring容器管理的对象。Bean默认是单例的,在spring加载时候默认就会创建这些bean对象,无论你用不用,都存在。
    • 我们可以通过修改xml中的bean class值,达到修改关联实现类的作用。例如A类中有个B类的对象,这种注入关系,也受到spring的自动管理。
  • DI: Dependency Injection 依赖注入

    • 运行过程中,动态向其他对象提供其依赖关联对象。其实现机制使用反射。
  • AOP:Asepct-Orentid Programming 面向切面编程
* @Component 表示该类需要在应用程序中被创建,受到spring容器管理,无需额外new
        需要写到实现类上,不要写到接口类上
        要解决单接口多继承实现类的歧义性,可使用
            1. @Primary 提高实现bean类的优先级,只能有一个primary
            2. @Qualifier("xxoo") 别名限定符,在component处声明别名,在autowired进行@Qualifier动态绑定
            3. @Component("xxoo") 和上面一样,bean id限定符,在component处声明别名,在autowired进行@Qualifier动态绑定
            4. 不指定Qualifier别名,也不指定Component的bean id,使用空id的@Component,则默认bean id是  类名首字母小写。使用时候依然在autowired进行@Qualifier动态绑定
            5. 当函数参数类型为父接口类,实现不明时,可以用 @Qualifier("xxoo")来修饰参数,以保证参数为指定子类型对象。
            6. 还可以使用 javax 的 Resource(name="xxoo"),来替代spring的 Autowired + Qualifier 做动态绑定
        compenent属于基本组件类,为符合web的三层结构,controller -> service -> dao ,所以现在推荐使用 @Controller @Service @Respository 三个业务功能注解,不推荐使用 @Compenent,但对不起,这三个新玩意儿和compenent本质上没区别,就是一个区别功能性的注释。
* @ComponentScan 表示自动发现该应用程序中需要被创建的类,自动扫描需要创建类
        注意,默认仅扫描本类所在包以及子包内的compenent。
        如需扫描其他包。
            1. 需要后面追加包名,例如 @ComponentScan("com.xxoo.project.package") 
            2. 或者 @ComponentScan(basePackages = {"com.xxoo.project.package1", "com.xxoo.project.package2"}),用来添加多包
            3. 或者@ComponentScan(basePackageClasses = {MyClass1.class, MyClass2.class}),这种方式方式是,当我们修改包名时不用修改代码
* @Autowired 自动满足bean之间的依赖,自动装配,自动依赖注入。
    使用环境
        可适用于构造函数,未使用反射,最为高效
        也可适用于setter方法以及普通方法
        也可使用于成员变量,最为方便
    特殊属性
        required=true/false
* @Configuration 表示该类当前是一个配置类,可以做到main和组件扫描进行分离

自动装配方式

  • 隐式自动装配【推荐】

    • 对类标注 @component注解,该类会被作为组件类,spring对该类创建 bean对象

    • 然后,一般创建一个空的配置类,该类进行 @componentScan 注解,该类必须为 @Configuration 类,表示spring将自动扫描该配置类所在包。然后在main中,使用 @ContextConfiguration 去加载配置类来进行使用,使用如下

    @ContextConfiguration(classes = AppConfig.class)
    
    • 一般配套使用 @autowired 进行bean自动装配依赖,加(required=false)进行控制;Qualifier来设置bean的id

    • 通常会注入构造函数或者setter方法

  • java显式装配

    • 一般是因为第三方库,我们不能修改去源代码加标注。这是需要显式的进行装配。

    • 通常先创建一个javaconfig类,里面不放业务逻辑代码,专门配置所需的bean,例如

    @Configuration
    @ContextConfiguration(locations = {"classpath:spring/spring-dao.xml","classpath:scan.xml"})
    public class bbsConfig{
      private Postdao postdao;
      private Userdao userdao;
      @Bean(name="postservice")
       public PostService getPost()
      {
        return new PostserviceImpl(postdao,userdao);
      }
    }
    
    • 此时,@Bean 对configration配置类中,@bean表示需要被自动装配的对象

    其使用方式,以及去除多义性的方式和自动装配一模一样。@bean 几乎等同于 @Component, 区别仅仅是后者修饰类(我们有源码,可以修改类代码),而前者@bean修饰一个函数(通常在appConfig配置类中),用这个函数创建第三方类对象。

  • XML配置方式【不太推荐】,就是在XML文件里面对bean做配置,实现自动依赖注入。一般叫 applicationContext.xml. 格式固定,例如

  <?xml version="1.0" encoding="UTF-8"?>
  <beans xmlns="http://www.springframework.org/schema/beans"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:context="http://www.springframework.org/schema/context"
         xsi:schemaLocation="http://www.springframework.org/schema/beans
          http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      ">
      <!--
          这里就是scan的子包名,相当于 @ComponentScan, 这是XML中启动扫描的方法
      -->
      <context:component-scan base-package="com.freeknight.demo" />
      <!--
        这部分描述需要被管理的组件名,相当于 @bean
          bean: 描述当前对象需要被spring对象管理
          id: 从spring容器中获取对象时候使用该id
          class: 需要被管理的对象类别全名
      -->
      <bean id="service" class="service.MessageService">
      </bean>
      <bean id="printer" class="service.MessagePrinter">
          <!-- 
            这部分描述依赖关系,可以不用额外手动指定。
              name 是函数参数名
              ref 是上面声明的bean id
           -->
          <property name="service" ref="service"></property>
      </bean>
  </beans>
  • 其中 bean id 就是bean对象的名字,唯一。
  • 其中 bean name是bean的别名,可以有多个别名,用分号空格逗号分开都可以。通过任何一个别名都可以获得对应的bean对象。
  • 其中可以通过元素进行构造函数的依赖注入。同样可以缩减为 “c-” 命名空间。

    • 可以复杂类型注入,包括 list, set, map, array, 以及对象ref,基本类型使用 value
  • 也可以通过元素进行属性注入,一般是利用set get方法。一样可以缩减为 “p-” 命名空间。
  • 还可以用 util- 命名空间 来做一些普通数据的定义,以方便 p- 注入。

注入后的使用如下:

  @ContextConfiguration("classpath:applicationContext.xml")
  • Bean的Scope作用域

    • Bean默认是单例的,无论你获取多少次,拿到的都是一个对象。

    • 但有些时候,我们希望Bean不是单例的,每次获取时能是一个新的对象,我们可以通过设定bean的作用于scope来达成,scope有四个值

    • singleton 默认,单例,只有一个bean实例

    • prototype 原型模式,每次注入或通过getbean上下文获取时,都会创建一个新的bean实例

    • session 会话模式,在web应用中,每个会话会创建一个bean实例

    • request 请求模式,在web应用中,对每个请求会创建一个bean实例

    • 限制scope

      <bean id="xxoo" class="com.freeknight.demo.xxoo" scope="singleton">
      </bean>
    
    • JAVA自动装配中
      @Component
      @Scope("session") // 或者@Scope(ConfigurableBeanFactory.SCOPE_SESSION)均可
      public class MyClass{ }
    
    • JAVA手动装配中
      @Configration
      public class AppConfig{
        @Bean
        @Scope("session")
        public MyClass getMyClass(){
            return new MyClass();
        }
      }
    
  • 延迟加载

    • 前提知识:

    • 在spring加载时候默认就会创建这些bean对象,无论你用不用,都存在。

    • 但有些时候我们不想开始花费时间进行bean对象创建和加载,我们需要使用时按需加载,则需要使用延迟加载,我们就需要使用 lazy-init

    • 注意:lazy延迟加载仅对singleton的scope有效,对于另外三种scope,默认就已经是lazy-init。

    • 延迟加载Lazy-init (该值默认为false; 设置为true则会开启延迟加载)

      <bean id="xxoo" class="com.freeknight.demo.xxoo" lazy-init=“true”>
      </bean>
    
    • JAVA自动装配中
      @Component
      @Lazy
      public class MyClass{ }
    
    • JAVA手动装配中
      @Configration
      public class AppConfig{
        @Bean
        @Lazy
        public MyClass getMyClass(){
            return new MyClass();
        }
      }
    
  • Bean对象的初始化和销毁函数

    • 当spring进行bean对象创建和销毁时,希望自动调用我们的初始化和释放函数.

    • 假设有一个JAVA类

    public class MyClass{ 
        public void myInit(){
                
        }
        public void myDestory(){
                
        }
    }
    
      <bean id="xxoo" class="com.freeknight.demo.xxoo" destory-method="myDestory" init-method="myInit">
      </bean>
    
    • JAVA自动装配中
      @Component
      public class MyClass{ 
          @PostConstruct
          public void myInit(){
                  
          }
          @PreDestory
          public void myDestory(){
                  
          }
      }
    
  • 工厂方法创建bean对象

    • 静态工厂方法 和 实例工厂方法

    • 假设我们有一个类

    public class Person{}
        
    public class PersonFactory{
        public static Person createPersonS(){
            return new Person();
        }
        public Person createPersonI(){
            return new Person();
        }
    }
    
      <!-- 静态工厂 -->
      <bean id="Person1" class="com.freeknight.demo.PersonFactory" factory-method="createPersonS">
      </bean>
      <!-- 实例工厂 -->
      <bean id="PersonFactory" class="com.freeknight.demo.PersonFactory" />
      <bean id="Person2" factory-bean="PersonFactory" factory-method="createPersonI"/>
    

其他扩展

  • log4j 添加pom的dependence,修改log4j.properties

  • junit 添加pom的dependence,在test目录下创建同名包,添加 @Test 函数测试

  • spring-test 添加pom的dependence,在test目录下创建同名包,添加 @RunWith(SpringJUnit4ClassRunner.class),加载配置类 @ContextConfiguration(classes=AppConfig.class)

spring, spring MVC, spring boot, spring cloud关系和区别

  • spring

    • 是一个大框架,包括众多衍生品,包括 spring boot, spring mvc, security, jpa等。但都基于IOC和AOP。
    • IOC提供依赖注入的容器,AOP解决面向切面的编程。
  • spring MVC

    • 是一个基于servlet的MVC框架,用来处理web开发的路径映射和视图渲染,解决WEB开发问题。
    • 它是spring框架里,关于web层开发的一部分
    • 一般网页服务开发,会分为三层。WEB层 -> service层 -> dao层 -> 数据库
    • 它和struts1, struts2平级,同样功能。
  • spring boot

    • 为了简化spring开发者的使用,而出来的一套快速开发整合包。它增加了约定大于配置理念,快速集成多个 spring插件。
    • 约定大于配置 :就是说如果没有做配置,就会使用默认配置,只有不符合默认值的配置,才需要额外配置。目的是让开发者减少复杂配置。
    • 它专注于开发微服务后台接口,不负责前端视图的开发。
  • spring cloud

    • 基于 spring boot 开发实现的一套云应用开发工具,它依赖于spring boot。
    • spring boot更关注于单一微服务开发,但spring cloud更关注于将spring boot开发的微服务进行整合和管理,它包括服务发现注册,配置中心,消息总线,负载均衡,断路器,数据监控,一键启动部署等功能。

spring boot基本概念

    • 和spring一起诞生的微框架,上手简单,配置依赖少(不用xml)
    • 可以不依赖容器(war包),直接独立运行
    • 可以可视化监控和性能检查等
    • 支持一个简单的 starter 依赖项,直接懒人包全部配置好(会略有依赖库的冗余)
    • 一般用在web项目中
    • 一般用在微服务开发
  • // demo1application.java
    @SpringBootApplication
    public class Demo1Application {
        public static void main(String[] args) {
            SpringApplication.run(Demo1Application.class, args);
        }
    }
    
    // 一个简单的controller
    @RestController
    public class HelloController {
        @RequestMapping("/hello")
        String index() {
            return "Hello Spring Boot";
        }
    }
    
    • 运行 demo1application.java,本地访问 localhost:8080/hello 进行API测试

这一切完全就是新瓶装老酒,我发现现在的技术 都特喜欢起新名词。

  • 为了解耦,把反射机制做了个规范化,使用注释和XML配置方法实现,这就是IOC,DI。
  • 啥TMD“约定大于配置”啊,任何一个ini config类,都有defaultvalue好吗?
  • 我一直讨厌小语法糖,看起来的确似乎可以省点事,但最终你都要去了解去本质,逃不掉的。但记住大量语法糖的规则,还需要浪费很多注意力。spring里面就大量的语法糖,恶心。
  • Bean的管理看起来很甜,问题是下面如何的对象管理都交给了别人,真的好不放心。原本java只是管理内存,现在都开始做对象管理了,很好。
  • 简直是标注狂+配置狂,下一步应该是自动化代码生成工具吧?类似unreal的blueprint?
  • 真能分层啊,view facade service dao mapper简直让人应接不暇,满地图的设计模式。

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK