Spring


所有内容为对“廖雪峰官网java教程”的整理
Spring官网
SpringBoot官网

Spring中需要注意的问题

  1. (70条消息) Spring Aop使用之避坑和cglib动态代理_ToString Zhang的博客-CSDN博客_ e n h a n c e r b y s p r i n g c g l i b enhancerbyspringcglib enhancerbyspringcglib
  2. Java代理(Proxy)模式 - 简书 (jianshu.com)
  3. (70条消息) Java中的实体类(entity class)和model_m1m-FG的博客-CSDN博客
  4. (70条消息) 什么是同源策略?_新手前端小鹿的博客-CSDN博客_同源策略

IoC容器

    什么是容器?容器是一种为某种特定组件的运行提供必要支持的一个软件环境。例如,Tomcat就是一个Servlet容器,它可以为Servlet的运行提供运行环境。类似Docker这样的软件也是一个容器,它提供了必要的Linux环境以便运行一个特定的Linux进程。
    Spring的核心就是提供了一个IoC容器,它可以管理所有轻量级的JavaBean组件,提供的底层服务包括组件的生命周期管理、配置和组装服务、AOP支持,以及建立在AOP基础上的声明式事务服务等。

  1. 原理:
    • IoC全称Inversion of Control,直译为控制反转。
    • 自己编写代码自行组装配置组件(javaBean)存在以下缺陷:
      • 谁负责创建组件?
        谁负责根据依赖关系组装组件?
        销毁时,如何按依赖顺序正确销毁?
    • 在IoC模式下,控制权发生了反转,即从应用程序转移到了IoC容器,所有组件不再由应用程序自己创建和配置,而是由IoC容器负责,这样,应用程序只需要直接使用已经创建好并且配置好的组件。为了能让组件在IoC容器中被“装配”出来,需要某种“注入”机制,例如,BookService自己并不会创建DataSource,而是等待外部通过setDataSource()方法来注入一个DataSource。
    • IoC又称为依赖注入(DI:Dependency Injection),它解决了一个最主要的问题:将组件的创建+配置与组件的使用相分离,并且,由IoC容器负责管理组件的生命周期。
    • 因为IoC容器要负责实例化所有的组件,因此,有必要告诉容器如何创建组件,以及各组件的依赖关系。一种最简单的配置是通过XML文件来实现:在Spring的IoC容器中,我们把所有组件统称为JavaBean,即配置一个组件就是配置一个Bean。
      <beans>
          <bean id="dataSource" class="HikariDataSource" />
          <bean id="bookService" class="BookService">
              <property name="dataSource" ref="dataSource" />
          </bean>
          <bean id="userService" class="UserService">
              <property name="dataSource" ref="dataSource" />
          </bean>
      </beans>
      
    • 依赖注入可以通过set()方法实现。但依赖注入也可以通过构造方法实现。
    • 无侵入容器:在设计上,Spring的IoC容器是一个高度可扩展的无侵入容器。所谓无侵入,是指应用程序的组件无需实现Spring的特定接口,或者说,组件根本不知道自己在Spring的容器中运行。这种无侵入的设计有以下好处:
      • 应用程序组件既可以在Spring的IoC容器中运行,也可以自己编写代码自行组装配置;
      • 测试的时候并不依赖Spring容器,可单独进行测试,大大提高了开发效率。
  2. 装配Bean
    <bean id="dataSource" class="com.zaxxer.hikari.HikariDataSource">
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test" />
        <property name="username" value="root" />
        <property name="password" value="password" />
        <property name="maximumPoolSize" value="10" />
        <property name="autoCommit" value="true" />
    </bean>
    
      • 每个<bean …>都有一个id标识,相当于Bean的唯一ID;
      • 在userServiceBean中,通过注入了另一个Bean;
      • Bean的顺序不重要,Spring根据依赖关系会自动正确初始化。
      • Spring容器是通过读取XML文件后使用反射完成的。
      • 如果注入的不是Bean,而是boolean、int、String这样的数据类型,则通过value注入,例如,创建一个HikariDataSource
    • 我们需要创建一个Spring的IoC容器实例,然后加载配置文件,让Spring容器为我们创建并装配好配置文件中指定的所有Bean,这只需要一行代码:ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
    • 从Spring容器中“取出”装配好的Bean然后使用它:取出(UserService userService = context.getBean(UserService.class);),接着正常调用即可。
    • Spring还提供另一种IoC容器叫BeanFactory,使用方式和ApplicationContext类似:BeanFactory factory = new XmlBeanFactory(new ClassPathResource("application.xml"));
    • BeanFactory和ApplicationContext的区别在于,BeanFactory的实现是按需创建,即第一次获取Bean时才创建这个Bean,而ApplicationContext会一次性创建所有的Bean。实际上,ApplicationContext接口是从BeanFactory接口继承而来的,并且,ApplicationContext提供了一些额外的功能,包括国际化支持、事件和通知机制等。通常情况下,我们总是使用ApplicationContext,很少会考虑使用BeanFactory。
  3. 使用注解Annotation配置(装配):
    • @Component注解就相当于定义了一个Bean,它有一个可选的名称,即小写开头的类名。
    • 使用@Autowired就相当于把指定类型的Bean注入到指定的字段中。和XML配置相比,@Autowired大幅简化了注入,因为它不但可以写在set()方法上,还可以直接写在字段上,甚至可以写在构造方法中。
    • 一般把@Autowired写在字段上,通常使用package权限的字段,便于测试。
    • 最后,编写一个主类启动容器:
      • @Configuration,表示它是一个配置类,因为我们创建ApplicationContext时:ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
      • @ComponentScan,它告诉容器,自动搜索当前类所在的包以及子包,把所有标注为@Component的Bean自动创建出来,并根据@Autowired进行装配。
    • 总结:使用Annotation配合自动扫描能大幅简化Spring的配置,我们只需要保证:
      • 每个Bean被标注为@Component并正确使用@Autowired注入;
      • 配置类被标注为@Configuration和@ComponentScan;
      • 所有Bean均在指定包以及子包内。
  4. 定制Bean组件
    • Scope:对于Spring容器来说,当我们把一个Bean标记为@Component后,它就会自动为我们创建一个单例(Singleton),即容器初始化时创建Bean,容器关闭前销毁Bean。在容器运行期间,我们调用getBean(Class)获取到的Bean总是同一个实例。
          还有一种Bean,我们每次调用getBean(Class),容器都返回一个新的实例,这种Bean称为Prototype(原型),它的生命周期显然和Singleton不同。声明一个Prototype的Bean时,需要添加一个额外的@Scope注解@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    • 注入List:Validators(注册时验证的总类)被注入了一个List,Spring会自动把所有类型为Validator的Bean装配为一个List注入进来,这样一来,我们每新增一个Validator类型,就自动被Spring装配到Validators中了,非常方便。
    • 可选注入:默认情况下,当我们标记了一个@Autowired后,Spring如果没有找到对应类型的Bean,它会抛出NoSuchBeanDefinitionException异常。可以给@Autowired增加一个required = false的参数:
    • 创建第三方Bean:如果一个Bean不在我们自己的package管理之内,例如ZoneId,如何创建它?答案是我们自己在@Configuration类中编写一个Java方法创建并返回它,注意给方法标记一个@Bean注解。
    • 初始化和销毁:些时候,一个Bean在注入必要的依赖后,需要进行初始化(监听消息等)。在容器关闭时,有时候还需要清理资源(关闭连接池等)。我们通常会在Bean内部定义一个init()方法进行初始化,定义一个shutdown()方法进行清理。在Bean的初始化和清理方法上标记@PostConstruct和@PreDestroy。
    • 使用别名:默认情况下,对一种类型的Bean,容器只创建一个实例。但有些时候,我们需要对一种类型的Bean创建多个实例。例如,同时连接多个数据库,就必须创建多个DataSource实例。
      • 可以用@Bean(“name”)指定别名,也可以用@Bean+@Qualifier(“name”)指定别名。
      • 在@Component修饰的类中,用@Qualifier(“相同name”)指定别名时,会报错可以用@Bean("name")指定别名,也可以用@Bean+@Qualifier("name")指定别名。。此时,指定名称不能重复,或者:把其中某个Bean指定为@Primary。
            这样,在注入时,如果没有指出Bean的名字,Spring会注入标记有@Primary的Bean。这种方式也很常用。例如,对于主从两个数据源,通常将主数据源定义为@Primary。其他Bean默认注入的就是主数据源。如果要注入从数据源,那么只需要指定名称即可。
      • **总结:**相同类型的Bean只能有一个指定为@Primary,其他必须用@Quanlifier(“beanName”)指定别名;
            注入时,可通过别名@Quanlifier(“beanName”)指定某个Bean;
    • 使用FactoryBean:我们在设计模式的工厂方法中讲到,很多时候,可以通过工厂模式创建对象。Spring也提供了工厂模式,允许定义一个工厂,然后由工厂创建真正的Bean。用工厂模式创建Bean需要实现FactoryBean接口。
      • 当一个Bean实现了FactoryBean接口后,Spring会先实例化这个工厂,然后调用getObject()创建真正的Bean。getObjectType()可以指定创建的Bean的类型,因为指定类型不一定与实际类型一致,可以是接口或抽象类。
      • 因此,如果定义了一个FactoryBean,要注意Spring创建的Bean实际上是这个FactoryBean的getObject()方法返回的Bean。为了和普通Bean区分,我们通常都以XxxFactoryBean命名。
  5. IOC容器使用recource:
    • 在Java程序中,我们经常会读取配置文件、资源文件等。使用Spring容器时,我们也可以把“文件”注入进来,方便程序读取。
    • Spring提供了一个org.springframework.core.io.Resource(注意不是jarkata.annotation.Resource或javax.annotation.Resource),它可以像String、int一样使用@Value注入
    • 注入Resource最常用的方式是通过classpath,即类似classpath:/logo.txt表示在classpath中搜索logo.txt文件,然后,我们直接调用Resource.getInputStream()就可以获取到输入流,避免了自己搜索文件的代码。
    • 最常用的注入是通过classpath以classpath:/path/to/file的形式注入。
  6. 注入配置:
    • 在开发应用程序时,经常需要读取配置文件。最常用的配置方法是以key=value的形式写在.properties文件中。
    • 我们可以使用上一节讲到的Resource来读取位于classpath下的一个app.properties文件。但是,这样仍然比较繁琐。
    • Spring容器还提供了一个更简单的@PropertySource来自动读取配置文件。我们只需要在@Configuration配置类上再添加一个注解:@PropertySource("app.properties")
    • Spring容器看到@PropertySource(“app.properties”)注解后,自动读取这个配置文件,然后,我们使用@Value正常注入
      • "${app.zone}"表示读取key为app.zone的value,如果key不存在,启动将报错;
      • "${app.zone:Z}"表示读取key为app.zone的value,但如果key不存在,就使用默认值Z。
      • **总结:**先使用@PropertySource读取配置文件,然后通过@Value以${key:defaultValue}的形式注入,可以极大地简化读取配置的麻烦。
    • 另一种注入配置的方式是先通过一个简单的JavaBean持有所有的配置,例如,一个SmtpConfig。然后,在需要读取的地方,使用#{smtpConfig.host}注入。注意观察#{}这种注入语法,它和${key}不同的是,#{}表示从JavaBean读取属性。
    • 使用一个独立的JavaBean持有所有属性,然后在其他Bean中以#{bean.property}注入的好处是,多个Bean都可以引用同一个Bean的某个属性。
  7. 使用条件装配:
    • 开发应用程序时,我们会使用开发环境,例如,使用内存数据库以便快速启动。而运行在生产环境时,我们会使用生产环境,例如,使用MySQL数据库。如果应用程序可以根据自身的环境做一些适配,无疑会更加灵活。Spring为应用程序准备了Profile这一概念,用来表示不同的环境。例如,我们分别定义开发(native)、测试(test)和生产(production)这3个环境。
    • 在运行程序时,加上JVM参数-Dspring.profiles.active=test就可以指定以test环境启动。
    • 实际上,Spring允许指定多个Profile,例如:-Dspring.profiles.active=test,master,可以表示test环境,并使用master分支代码。
    • 要满足多个Profile条件,可以这样写:@Profile({ "test", "master" }) // 满足test或master
    • 除了根据@Profile条件来决定是否创建某个Bean外,Spring还可以根据@Conditional决定是否创建某个Bean。
      • @Conditional(OnSmtpEnvCondition.class)它的意思是,如果满足OnSmtpEnvCondition的条件,才会创建SmtpMailService这个Bean。
      • Spring只提供了@Conditional注解,具体判断逻辑还需要我们自己实现。Spring Boot提供了更多使用起来更简单的条件注解。例如,如果配置文件中存在app.smtp=true,则创建MailService。

AOP

    Object Oriented Programming,OOP作为面向对象编程的模式,获得了巨大的成功,OOP的主要功能是数据封装、继承和多态。
    Aspect Oriented Programming,AOP是一种新的编程方式,它和OOP不同,OOP把系统看作多个对象的交互,AOP把系统分解为不同的关注点,或者称之为切面(Aspect)。
    对于安全检查、日志、事务等代码,它们会重复出现在每个业务方法中。使用OOP,我们很难将这些四处分散的代码模块化。考察业务模型可以发现,BookService关心的是自身的核心逻辑,但整个系统还要求关注安全检查、日志、事务等功能,这些功能实际上“横跨”多个业务方法,为了实现这些功能,不得不在每个业务方法上重复编写代码。
    一种可行的方式是使用Proxy模式,将某个功能,例如,权限检查,放入Proxy中。这种方式的缺点是比较麻烦,必须先抽取接口,然后,针对每个方法实现Proxy。既然SecurityCheckBookService的代码都是标准的Proxy样板代码,不如把权限检查视作一种切面(Aspect),把日志、事务也视为切面,然后,以某种自动化的方式,把切面织入到核心逻辑中,实现Proxy模式。    然后,以某种方式,让框架来把上述3个Aspect以Proxy的方式“织入”到BookService中,这样一来,就不必编写复杂而冗长的Proxy模式。
    AOP原理:
    如果客户端获得了BookService的引用,当调用bookService.createBook()时,如何对调用方法进行拦截,并在拦截前后进行安全检查、日志、事务等处理,就相当于完成了所有业务功能。
     在Java平台上,对于AOP的织入,有3种方式:

  • 编译期:在编译时,由编译器把切面调用编译进字节码,这种方式需要定义新的关键字并扩展编译器,AspectJ就扩展了Java编译器,使用关键字aspect来实现织入;
  • 类加载器:在目标类被装载到JVM时,通过一个特殊的类加载器,对目标类的字节码重新“增强”;
  • 运行期:目标对象和切面都是普通Java类,通过JVM的动态代理功能或者第三方库实现运行期动态织入。
         最简单的方式是第三种,Spring的AOP实现就是基于JVM的动态代理。由于JVM的动态代理要求必须实现接口,如果一个普通类没有业务接口,就需要通过CGLIB或者Javassist这些第三方库实现。
    什么是代理: 将目标类(或一个已知接口)封装为代理类,该代理类增强某些功能(例如,鉴权、延迟加载、连接池复用等),要求该代理类和目标类接口类型完全一致。
         AOP技术看上去比较神秘,但实际上,它本质就是一个动态代理,让我们把一些常用功能如权限检查、日志、事务等,从每个业务方法中剥离出来。
  1. 装配AOP(AspectJ)
    • AOP术语:
      • Aspect:切面,即一个横跨多个核心逻辑的功能,或者称之为系统关注点;
        Joinpoint:连接点,即定义在应用程序流程的何处插入切面的执行;
        Pointcut:切入点,即一组连接点的集合;
        Advice:增强,指特定连接点上执行的动作;
        Introduction:引介,指为一个已有的Java对象动态地增加新的接口;
        Weaving:织入,指将切面整合到程序的执行流程中;
        Interceptor:拦截器,是一种实现增强的方式;
        Target Object:目标对象,即真正执行业务的核心逻辑对象;
        AOP Proxy:AOP代理,是客户端持有的增强后的对象引用。
    • maven引入org.springframework:spring-aspects:6.0.0依赖会自动引入AspectJ,使用AspectJ实现AOP比较方便,因为它的定义比较简单。
    • 虽然Spring容器内部实现AOP的逻辑比较复杂(需要使用AspectJ解析注解,并通过CGLIB实现代理类),但我们使用AOP非常简单,一共需要三步:
      • 定义执行方法,并在方法上通过AspectJ的注解告诉Spring应该在何处调用此方法;
      • 标记@Component和@Aspect;@Before("execution(public * com.itranswarp.learnjava.service.*.*(..))")
      • 在@Configuration类上标注@EnableAspectJAutoProxy。
    • Spring也提供其他方法来装配AOP,但都没有使用AspectJ注解的方式来得简洁明了。
    • 拦截器类型:
      • @Before:这种拦截器先执行拦截代码,再执行目标代码。如果拦截器抛异常,那么目标代码就不执行了;
        @After:这种拦截器先执行目标代码,再执行拦截器代码。无论目标代码是否抛异常,拦截器代码都会执行;
        @AfterReturning:和@After不同的是,只有当目标代码正常返回时,才执行拦截器代码;
        @AfterThrowing:和@After不同的是,只有当目标代码抛出了异常时,才执行拦截器代码;
        @Around:能完全控制目标代码是否执行,并可以在执行前后、抛异常后执行任意拦截代码,可以说是包含了上面所有功能。
  2. 使用注解装配AOP:
    • 我们在使用AOP时,要注意到虽然Spring容器可以把指定的方法通过AOP规则装配到指定的Bean的指定方法前后,但是,如果自动装配时,因为不恰当的范围,容易导致意想不到的结果,即很多不需要AOP代理的Bean也被自动代理了,并且,后续新增的Bean,如果不清楚现有的AOP装配规则,容易被强迫装配。
    • 使用AOP时,被装配的Bean最好自己能清清楚楚地知道自己被安排了。例如,Spring提供的@Transactional就是一个非常好的例子。如果我们自己写的Bean希望在一个数据库事务中被调用,就标注上@Transactional。
    • 通过@Transactional,某个方法是否启用了事务就一清二楚了。因此,装配AOP的时候,使用注解是最好的方式。
    • 注解装配AOP步骤:
      • 定义一个注解或者使用已有的注解;
      • 核心逻辑:
        • 依据注解在需要切面的地方标注
      • 切面方法:
        • @Aspect标示Bean
        • @拦截器(“Annotation(切面方法参数)”)
  3. AOP避坑(NPE异常):
    深入理解Spring使用CGLIB生成Proxy的原理:
    • 第一步,正常创建一个UserService的原始实例,这是通过反射调用构造方法实现的,它的行为和我们预期的完全一致;
    • 第二步,通过CGLIB创建一个UserService的子类,并引用了原始实例和LoggingAspect;
    • 如果我们观察Spring创建的AOP代理,它的类名总是类似UserService$$EnhancerBySpringCGLIB$$1c76af9d(你没看错,Java的类名实际上允许$字符)。为了让调用方获得UserService的引用,它必须继承自UserService。然后,该代理类会覆写所有public和protected方法,并在内部将调用委托给原始的UserService实例。出现了两个UserService实例:一个是我们代码中定义的原始实例,第二个是引用了原始的UserService实例。
    • 对于Spring通过CGLIB动态创建的UserService$$EnhancerBySpringCGLIB代理类,它的构造方法中,并未调用super(),因此,从父类继承的成员变量,包括final类型的成员变量,统统都没有初始化。
    • 自动加super()的功能是Java编译器实现的,它发现你没加,就自动给加上,发现你加错了,就报编译错误。但实际上,如果直接构造字节码,一个类的构造方法中,不一定非要调用super()。Spring使用CGLIB构造的Proxy类,是直接生成字节码,并没有源码-编译-字节码这个步骤.
    • 正确使用AOP避坑指南:
      • 访问被注入的Bean时,总是调用方法而非直接访问字段;
      • 编写Bean时,如果可能会被代理,就不要编写public final方法。
    • 总结:
      • 由于Spring通过CGLIB实现代理类,我们要避免直接访问Bean的字段,以及由final方法带来的“未代理”问题。
      • 遇到CglibAopProxy的相关日志,务必要仔细检查,防止因为AOP出现NPE异常。

Spring访问数据库

  1. 使用JDBC(相对于DAO,数据库的使用分散在各个子类中):
    • 在Spring使用JDBC,首先我们通过IoC容器创建并管理一个DataSource实例,然后,Spring提供了一个JdbcTemplate,可以方便地让我们操作JDBC,因此,通常情况下,我们会实例化一个JdbcTemplate。顾名思义,这个类主要使用了Template模式(定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构,只是重定义该算法的某些特定步骤)。
    • 通过@PropertySource(“jdbc.properties”)读取数据库配置文件;
      通过@Value(“${jdbc.url}”)注入配置文件的相关配置;
      创建一个DataSource实例,它的实际类型是HikariDataSource,创建时需要用到注入的配置;
      创建一个JdbcTemplate实例,它需要注入DataSource,这是通过方法参数完成注入的。
    • JdbcTemplate用法:
      • T execute(ConnectionCallback action)方法,它提供了Jdbc的Connection供我们使用;
      • 回调函数:(70条消息) 通俗理解“回调函数”_昂刺鱼人工智能的博客-CSDN博客_回调函数
        10张图让你彻底理解回调函数 - 知乎 (zhihu.com)
      • T execute(String sql, PreparedStatementCallback action)的用法;T queryForObject(String sql, RowMapper rowMapper, Object… args)方法;在queryForObject()方法中,传入SQL以及SQL参数后,JdbcTemplate会自动创建PreparedStatement,自动执行查询并返回ResultSet,我们提供的RowMapper需要做的事情就是把ResultSet的当前行映射成一个JavaBean并返回。整个过程中,使用Connection、PreparedStatement和ResultSet都不需要我们手动管理。
      • RowMapper不一定返回JavaBean,实际上它可以返回任何Java对象。例如,使用SELECT COUNT(*)查询时,可以返回Long。
      • query()方法传入的参数仍然是SQL、SQL参数以及RowMapper实例。这里我们直接使用Spring提供的BeanPropertyRowMapper。如果数据库表的结构恰好和JavaBean的属性名称一致,那么BeanPropertyRowMapper就可以直接把一行记录按列名转换为JavaBean。
      • 如果我们执行的不是查询,而是插入、更新和删除操作,那么需要使用update()方法
      • 只有一种INSERT操作比较特殊,那就是如果某一列是自增列(例如自增主键),通常,我们需要获取插入后的自增值。JdbcTemplate提供了一个KeyHolder来简化这一操作。
  2. 使用声明式事务:Spring提供了一个PlatformTransactionManager来表示事务管理器,在主类中注释下;创建声明式事务注解@EnableTransactionManagement // 启用声明式;对需要事务支持的方法,加一个@Transactional注解。
    • 声明式事务的支持也是AOP原理,声明了@EnableTransactionManagement后,不必额外添加@EnableAspectJAutoProxy。
    • 回滚事务:spring声明式事务会自动回滚,为了简化代码,强烈建议业务异常体系从RuntimeException派生,这样就不必声明任何特殊异常即可让Spring的声明式事务正常工作。
    • 事务边界:事务的开始结束
    • 事务传播:一个事务A中还有一个事务B,那么spring遇到事务B的时候,会默认为事务B是在事务A的事务边界内执行的。
    • 一个事务方法如何获知当前方法中存在事务:使用ThreadLocal。Spring总是把JDBC相关的Connection和TransactionStatus实例绑定到ThreadLocal。如果一个事务方法从ThreadLocal未取到事务,那么它会打开一个新的JDBC连接,同时开启一个新的事务,否则,它就直接使用从ThreadLocal获取的JDBC连接以及TransactionStatus。
    • **总结:**Spring提供的声明式事务极大地方便了在数据库中使用事务,正确使用声明式事务的关键在于确定好事务边界,理解事务传播级别。
  3. 使用DAO(Data Access Object):
    • 在传统的多层应用程序中,通常是Web层调用业务层,业务层调用数据访问层。业务层负责处理各种业务逻辑,而数据访问层只负责对数据进行增删改查。因此,实现数据访问层就是用JdbcTemplate实现对数据库的操作。
    • Spring提供了一个JdbcDaoSupport类,用于简化DAO的实现。这个JdbcDaoSupport没什么复杂的,核心代码就是持有一个JdbcTemplate。
    • 封装一个JdbcDaoSupport类的子类的抽象类,在该抽象类中,实现JdbcTemplate对数据库的各种操作。
    • 可以基于泛型实现更通用、更简洁的DAO模式。
  4. 集成Hibernate(ORM冬眠):
    • 把关系数据库的表记录映射为Java对象的过程就是ORM:Object-Relational Mapping。ORM既可以把记录转换成Java对象,也可以把Java对象转换为行记录。
    • 使用JdbcTemplate配合RowMapper可以看作是最原始的ORM。如果要实现更自动化的ORM,可以选择成熟的ORM框架,例如Hibernate。
    • 在Spring中集成Hibernate需要配置的Bean如下:DataSource;LocalSessionFactory;HibernateTransactionManager。
    • 尽量使用Annotation配置所有的Entity Bean。
  5. JPA
    • JPA(Java Persistence API)就是JavaEE的一个ORM标准,它的实现其实和Hibernate没啥本质区别,但是用户如果使用JPA,那么引用的就是jakarta.persistence这个“标准”包,而不是org.hibernate这样的第三方包。因为JPA只是接口,所以,还需要选择一个实现产品,跟JDBC接口和MySQL驱动一个道理。
    • 使用JPA时也完全可以选择Hibernate作为底层实现,但也可以选择其它的JPA提供方,比如EclipseLink。Spring内置了JPA的集成,并支持选择Hibernate或EclipseLink作为实现。这里我们仍然以主流的Hibernate作为JPA实现为例子,演示JPA的基本用法。
  6. 集成myBatis
    介于全自动ORM如Hibernate和手写全部如JdbcTemplate之间,还有一种半自动的ORM,它只负责把ResultSet自动映射到Java Bean,或者自动填充Java Bean参数,但仍需自己写出SQL。MyBatis就是这样一种半自动化ORM框架。
  7. 设计ORM

开发web(spring mvc)应用

  1. spring mvc具体原理
  2. rest(请求响应 json结构)
  3. spring mvc中加入fliter
  4. 比fliter功能更高级的interceptor
  5. 处理服务端异步请求,cors
  6. 国际化
  7. 异步处理
  8. 在http协议封装一层的websocket协议
  9. 集成第三方组件:javamail、JMS(java message service):Active MQ artemis、定时器Scheduler、JMX(Java Management Extensions)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

古剑诛仙

你的鼓励是我创造的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值