spring学习


1,spring

Spring中国教育管理中心

Spring认证概述

Spring认证框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理的轻量级容器(lightweight container)。 [1] Spring是Java EE编程领域的一个轻量级开源框架,该框架由一个叫Rod Johnson的程序员在 2002 年最早提出并随后创建,是为了解决企业级编程开发中的复杂性,实现敏捷开发的应用型框架 。 [2]

教育中心概述

2021年2月,VMware公司授权北京中科卓望网络科技有限公司正式成为VMware Tunzu Spring中国教育管理中心,负责Spring国际认证体系标准在中国教育行业的推广工作。 [3]

Spring框架是由于[软件开发](https://baike.baidu.com/item/软件开发/3448966)的复杂性而创建的。Spring使用的是基本的JavaBean来完成以前只可能由[EJB](https://baike.baidu.com/item/EJB/144195)完成的事情。然而,Spring的用途不仅仅限于服务器端的开发。从简单性、可测试性和松耦合性角度而言,绝大部分Java应用都可以从Spring中受益。

Spring的形成,最初来自Rod Jahnson所著的一本很有影响力的书籍《Expert One-on-One J2EE Design and Development》,就是在这本书中第一次出现了Spring的一些核心思想,该书出版于2002年。另外一本书《Expert One-on-One J2EE Development without EJB》,更进一步阐述了在不使用EJB开发JAVA EE企业级应用的一些设计思想和具体的做法。

Spring的初衷:

1、JAVA EE开发应该更加简单。

2、使用接口而不是使用类,是更好的编程习惯。Spring将使用接口的复杂度几乎降低到了零。

3、为JavaBean提供了一个更好的应用配置框架。

4、更多地强调[面向对象](https://baike.baidu.com/item/面向对象)的设计,而不是现行的技术如JAVA EE。

5、尽量减少不必要的异常捕捉。

6、使应用程序更加容易测试。

Spring的目标:

1、可以令人方便愉快的使用Spring。

2、应用程序代码并不依赖于Spring APIs。

3、Spring不和现有的解决方案竞争,而是致力于将它们融合在一起。

Spring的基本组成:

1、最完善的轻量级核心框架。

2、通用的事务管理抽象层。

3、JDBC抽象层。

4、集成了Toplink, Hibernate, JDO, and iBATIS SQL Maps。

5、AOP功能。

6、灵活的MVC Web应用框架。

优点

◆JAVA EE应该更加容易使用。

◆面向对象的设计比任何实现技术(比如JAVA EE)都重要。

◆[面向接口编程](https://baike.baidu.com/item/面向接口编程/6025286),而不是针对类编程。Spring将使用接口的复杂度降低到零。(面向接口编程有哪些复杂度?)

◆代码应该易于测试。Spring框架会帮助你,使代码的测试更加简单。

◆JavaBean提供了应用程序配置的最好方法。

◆在Java中,已检查异常(Checked exception)被过度使用。框架不应该迫使你捕获不能恢复的异常。

简介

2002年:首次推出了Spring框架的雏形:interface 21 框架

Spring:

Spring是一个开源框架,它由[Rod Johnson](https://baike.baidu.com/item/Rod Johnson)创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。

轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。

控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。

面向切面——Spring提供了[面向切面编程](https://baike.baidu.com/item/面向切面编程)的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。

容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。

框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。

所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

Spring框架由七个定义明确的模块组成(图1.1)。

(Spring框架概览图1.1)

如果作为一个整体,这些模块为你提供了开发企业应用所需的一切。但你不必将应用完全基于Spring框架。你可以自由地挑选适合你的应用的模块而忽略其余的模块。

就像你所看到的,所有的Spring模块都是在核心容器之上构建的。容器定义了Bean是如何创建、配置和管理的——更多的Spring细节。当你配置你的应用时,你会潜在地使用这些类。但是作为一名开发者,你最可能对影响容器所提供的服务的其它模块感兴趣。这些模块将会为你提供用于构建应用服务的框架,例如AOP和持久性。

核心容器

这是Spring框架最基础的部分,它提供了依赖注入(DependencyInjection)特征来实现容器对Bean的管理。这里最基本的概念是BeanFactory,它是任何Spring应用的核心。BeanFactory是工厂模式的一个实现,它使用IoC将应用配置和依赖说明从实际的应用代码中分离出来。

应用上下文(Context)模块

核心模块的BeanFactory使Spring成为一个容器,而上下文模块使它成为一个框架。这个模块扩展了BeanFactory的概念,增加了对国际化(I18N)消息、事件传播以及验证的支持。

另外,这个模块提供了许多企业服务,例如电子邮件、JNDI访问、EJB集成、远程以及时序调度(scheduling)服务。也包括了对模版框架例如Velocity和FreeMarker集成的支持。

Spring的AOP模块

Spring在它的AOP模块中提供了对面向切面编程的丰富支持。这个模块是在Spring应用中实现切面编程的基础。为了确保Spring与其它AOP框架的互用性,Spring的AOP支持基于AOP联盟定义的API。AOP联盟是一个开源项目,它的目标是通过定义一组共同的接口和组件来促进AOP的使用以及不同的AOP实现之间的互用性。通过访问他们的站点,你可以找到关于AOP联盟的更多内容。

Spring的AOP模块也将元数据编程引入了Spring。使用Spring的元数据支持,你可以为你的源代码增加注释,指示Spring在何处以及如何应用切面函数。

JDBC抽象和DAO模块

使用JDBC经常导致大量的重复代码,取得连接、创建语句、处理结果集,然后关闭连接。Spring的JDBC和DAO模块抽取了这些重复代码,因此你可以保持你的数据库访问代码干净简洁,并且可以防止因关闭数据库资源失败而引起的问题。

这个模块还在几种[数据库服务器](https://baike.baidu.com/item/数据库服务器/613818)给出的错误消息之上建立了一个有意义的异常层。使你不用再试图破译神秘的私有的SQL错误消息!

另外,这个模块还使用了Spring的AOP模块为Spring应用中的对象提供了事务管理服务。

对象/关系映射集成模块

对那些更喜欢使用对象/关系映射工具而不是直接使用JDBC的人,Spring提供了ORM模块。Spring并不试图实现它自己的ORM解决方案,而是为几种流行的[ORM框架](https://baike.baidu.com/item/ORM框架/15541111)提供了集成方案,包括Hibernate、JDO和iBATIS SQL映射。Spring的事务管理支持这些ORM框架中的每一个也包括JDBC。

Spring的Web模块

Web上下文模块建立于应用上下文模块之上,提供了一个适合于Web应用的上下文。另外,这个模块还提供了一些面向服务支持。例如:实现文件上传的multipart请求,它也提供了Spring和其它Web框架的集成,比如Struts、WebWork。

Spring的**MVC框架**

Spring为构建Web应用提供了一个功能全面的MVC框架。虽然Spring可以很容易地与其它MVC框架集成,例如Struts,但Spring的MVC框架使用IoC对控制逻辑和业务对象提供了完全的分离。

它也允许你声明性地将请求参数绑定到你的业务对象中,此外,Spring的MVC框架还可以利用Spring的任何其它服务,例如国际化信息与验证。

Spring框架Web页面乱码问题

在做java Web 项目时,乱码问题时常都会出现,解决方法也不尽相同,有简单也有复杂的;如果加入了Spring框架之后就不一样了,可以采用Spring框架自带的过滤器CharacterEncodingFilter,这样可以大大减轻了我们的工作量,即简单方便又容易理解,配置方式如下:在web.xml文件中filter的位置加上如下内容:


    encodingFilter
    
        org.springframework.web.filter.CharacterEncodingFilter
    
    
        encoding
        UTF-8
    
    
        forceEncoding
        true
    


    encodingFilter
    *

SSH: struct2 spring hibernate

SSM: springMVC spring +Mybatis

官网: https://spring.io/projects/spring-framework

官方下载地址: http://repo.spring.io/release/org/springframework/spring

**GitHub地址:**https://github.com/spring-projects/spring-framework

Maven 依赖



    org.springframework
    spring-webmvc
    5.3.4




    org.springframework
    spring-jdbc
    5.3.4

1.2、优点

  • Spring是开源免费的框架(容器)
  • Spring是一个轻量级、非入侵式的框架
  • 核心是 控制反转(IOC)面向切面编程(AOP)
  • 支持事务处理,对框架的整合的支持!

总结:Spring就是一个轻量级的控制反转(IOC),**面向切面编程(AOP)**的框架!

Spring的官网介绍:现代化Java开发

  • Spring Boot

    • 一个快速开发的脚手架

    • 基于SpringBoot可以快速的开发单个微服务

    • 约定大于配置

  • Spring Cloud

    • SpringCloud 是基于SpringBoot实现的。

大多数公司都在使用Spring Boot进行快速开发

学习SpringBoot的前提,需要为完全掌握Spring及其SpringMVC

唯一弊端缺点:发展太久,配置十分繁琐,人称 “配置地狱”

2,IOC理论推导

传统的设计模式:
  1. 实体类接口 UserDao 接口

  2. 实体类接口实现类 UserDaoImpl 类

  3. 业务层实现接口 UserServive 接口

  4. 业务层实现类 UserServiceImpl 类

package com.hjf.dao;

public interface UserDao {
    void getuser();
}
package com.hjf.dao;
public class UserDaoImpl implements UserDao{

    public void getuser() {
        System.out.println("默认获取用户数据");
    }
}
package com.hjf.service;

public interface UserService {
    void getuser();
}
package com.hjf.service;

import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;

public class UserServiceImpl implements UserService{

    private UserDao userDao = new UserDaoMysolImpl();

    public void getuser() {
        userDao.getuser();
    }
}
import com.hjf.dao.UserDaoImpl;
import com.hjf.service.UserServiceImpl;


public class MyTest {
    public static void main(String[] args) {
// 用户实际调用的是业务层,dao层他们不需要接触!
        UserServiceImpl userService = new UserServiceImpl();
        userService.getuser();
    }
}
问题提出
  1. 当实体类接口的实现类增加时
  2. 用户想要修改调用新的实体类接口时,就不得不修改 UserServiceImpl 实现类的代码。
package com.hjf.dao;
//新增的dao层实体类
public class UserDaoMysolImpl implements UserDao{

    public void getuser() {
        System.out.println("Mysql获取用户数据!");
    }
}
package com.hjf.service;

import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;

public class UserServiceImpl implements UserService{
    //修改需要新实现的接口,如果接口过多,且用户需要过多,会大量增加程序员的负担
    private UserDao userDao = new UserDaoMysolImpl();

    public void getuser() {
        userDao.getuser();
    }
}
问题解决
  • 在 UserServiceImpl 实现类中使用 set 注入来解决,重复修改代码的方法
  • 将在 UserServiceImpl 业务层,需要什么接口的实现类,就可以调用什么接口的实现类
package com.hjf.service;

import com.hjf.dao.UserDao;
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;

public class UserServiceImpl implements UserService{
    //修改需要新实现的接口,如果接口过多,且用户需要过多,会大量增加程序员的负担
//   解决方法:新增一个setter方法,将选择权交给客户,让用户选择实现类
//核心思想,将类设计成变量,利用 set 注入,就可以减少程序员的工作量这就是 IOC理论 控制反转
    private UserDao userDao;

    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void getuser() {
        userDao.getuser();
    }
}
import com.hjf.dao.UserDaoImpl;
import com.hjf.dao.UserDaoMysolImpl;
import com.hjf.service.UserServiceImpl;


public class MyTest {
    public static void main(String[] args) {
// 用户实际调用的是业务层,dao层他们不需要接触!
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDao(new UserDaoImpl());
        userService.getuser();
    }
}
  • 之前,程序是主动创建对象,控制权在程序员手上
  • 使用 set注入后,程序不再具有主动性,而是变成了被动接受对象!

IOC 思想,从本质上解决了问题,程序员不用再去管理对象,系统耦合度大大降低。这就是 IOC 原型

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

IoC是Spring框架的核心内容,使用多种方式完美的实现了IoC,可以使用XML配置,也可以使用注解,新版本的Spring也可以零配置实现IoC。

Spring容器在初始化时先读取配置文件,根据配置文件或元数据创建与组织对象存入容器中,程序使用时再从Ioc容器中取出需要的对象。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。

container magic

3,第一个Spring

1、Hello Spring
  1. 导入依赖

  2. 创建实体类

    核心是用 set 注入,实体类必须要有 set 方法

  3. 编写类的配置文件

  4. 测试

package com.hjf.pojo;
//实体类
public class Hello {
    private String str ;
    

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}

创建beans.xml文件

<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


        
                
        


测试类

import com.hjf.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
//        获取spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//        我们的对象现在都在spring中管理了,我们要使用,直接去里面取出来就可以
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());

    }
}
IOC理论推导用另一个方法xml配置写

编写xml 文件

<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

        
        
        
        
            
        



编写测试类MyTest

//import com.hjf.dao.UserDaoImpl;
//
//import com.hjf.service.UserServiceImpl;


import com.hjf.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
//        第一种获取数据的方法
// 用户实际调用的是业务层,dao层他们不需要接触!
//        UserServiceImpl userService = new UserServiceImpl();
//        userService.setUserDao(new UserDaoImpl()
//        );
//        userService.getuser();

//        第二种获取数据的方法
//   获取ApplicationContext;拿到spring的容器
         // 获取操作类的 容器(框架)
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");

        //    容器在手,天下我有,需要什么,直接get什么!
         // 获取要操作的类的 变量
        UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");

         // 执行方法
        userServiceImpl.getuser();
    }
}

到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xmI配置文件中进行修改,所谓的IpC,-句话搞定:对象由Spring来创建,管理,装配!

4,IOC创建对象方式

1、Spring 无参构造

  • Spring 构建时,默认走无参构造.
  • 当无参构造被有参构造,消除时,有 3 种(有参构造方式)注入方式,进行配置 类的加载文件 beans.xml

2、Spring 有参构造

  1. 下标构造注入

    
            
                
            
    

2.类型匹配注入


        
            
        

3.属性名注入(推荐使用)


        
            
        

总结:在配置文件加载的时候,容器bean中管理的对象就已经初始化了

5,spring配置

1、别名

        
2、Bean 配置

        
            
        
3、import

一般它用于团队开发,他可以将多个配置文件合并为一个 内容相同会自动优化


<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    
    
    

6,依赖注入

1、构造器注入(上面已经写了)

2、Set注入【重点】
  • 依赖注入:Set注入!
    • **Dependency **依赖:bean对象的创建依赖于容器
    • Injection注入:bean对象中的所有属性,由容器来注入

【环境搭建】

  1. 复杂类型

    public class Address {
        private String address;
    
        public String getAddress() {
            return address;
        }
    
        public void setAddress(String address) {
            this.address = address;
        }
    }
    
  2. 真实测试对象

    public class Student {
        private String name;
        private Address address;
        private String[] books;
        private List hobbys;
        private Map card;
        private Set games;
        private String wife;
        private Properties info;
    }
    

3.beans.xml

<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    

        
    


4.测试类

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.getAddress());
    }
}

5.不同对象类型注入方式

    
        
    

    

        

        


        
            
                红楼梦
                三国演义
                水浒传
                西游记
            
        


        
            
                唱歌
                看到电视
                听歌
            
        


        
            
                
                
            
        


        
            
                lol
                bob
                coc
            
        


        
            
        


        
            
                12334
                
                大法官
            
        

    

对应的测试及结果

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Student student = (Student) context.getBean("student");
        System.out.println(student.toString());
    }
/*    Student{
    name='雪女',
    address=Address{address='华夏'},
    books=[红楼梦, 三国演义, 水浒传, 西游记],
    hobbys=[唱歌, 看到电视, 听歌],
    card={
         身份证=333223323233242343,
         银行卡=242454656565656565},
    games=[lol, bob, coc],
    wife='null',
    info={
         性别=男,
         driver=12334,
         姓名=大法官}
    }*/
}
3,扩展方式注入

即 p 命名空间和 c 命名空间进行注入

官方解释

实现

  注意记得写       xmlns:p="http://www.springframework.org/schema/p"
                 xmlns:c="http://www.springframework.org/schema/c"

<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">


    


    







测试

@Test
public void test2(){
    ApplicationContext context = new ClassPathXmlApplicationContext("Userbeans.xml");
    User user = (User) context.getBean("user4");
  /*  User user = context.getBean("user2", User.class);*/
    System.out.println(user);
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"

测试时要导入junit依赖


    junit
    junit
    4.13

4,Bean的作用域

官方文档

1,单列模式The Singleton Scope(Spring 默认机制)初始new 一次,后面都不new 快速 线程不安全 对象一样,是同一个,单线程使用


2,原型模式The Prototype Scope:每次从容器getBean的时候,都会产生一个new对象 ,new浪费资源,但线程安全,多线程使用


3,其余request,application,websocket,session 这些只会在web开发中使用

7,bean的自动装配

  • 自动装配是 Spring 满足 Bean依赖的一种方式!

  • Spring 会在上下文中寻找,并给 Bean 自动装配属性!

    在 Spring 中的三种装配的方式

  1. 在 xml 中显示的装配
  2. 在 Java 中显示装配
  3. 隐式的自动装配 Bean 【重点】
1,测试

环境搭建:一个人两个宠物

package com.hjf.pojo;

public class Cat {
    public void shout(){
        System.out.println("miao~");
    }
}
package com.hjf.pojo;

public class Dog {
    public void shout(){
        System.out.println("wang~");
    }
}
package com.hjf.pojo;

public class People {
    private Cat cat;
    private Dog dog;
    private String name;

    @Override
    public String toString() {
        return "People{" +
                "cat=" + cat +
                ", dog=" + dog +
                ", name='" + name + '\'' +
                '}';
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    
    

    
        
        
        
    







环境测试

import com.hjf.pojo.People;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    @Test
    public void test1(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        People people = context.getBean("people", People.class);
        people.getCat().shout();
        people.getDog().shout();

    }
}
2,byName自动装配
   
    


    
        
    
3,byType自动装配
    
    


    
        
    

小结:byname的时候,需要保证所有bean的id唯一,并且这个bean的 id 需要和自动注入的属性的set方法的值一致!

bytype的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致!

4,使用注解实现自动装配

jdk1.5支持的注解,spring2.5就支持了!

The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML

使用注解须知:

1.导入约束:context约束

? **xmlns:context="http://www.springframework.org/schema/context" **

2.配置注解的支持:https://baike.baidu.com/item/面向切面编程/6016335),通过[预编译](https://baike.baidu.com/item/预编译/3191547)方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是[OOP](https://baike.baidu.com/item/OOP)的延续,是软件开发中的一个热点,也是[Spring](https://baike.baidu.com/item/Spring)框架中的一个重要内容,是[函数式编程](https://baike.baidu.com/item/函数式编程/4035031)的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的[耦合度](https://baike.baidu.com/item/耦合度/2603938)降低,提高程序的可重用性,同时提高了开发的效率。

11.2 AOP在Spring中的作用

提供声明式事务;允许用户自定义切面

  • 横切关注点:跨越应用程序多个模块的方法或功能。即是,与我们业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等…
  • 切面(ASPECT):横切关注点被模块化的特殊对象。即,它是一个类。
  • 通知(Advice):切面必须要完成的工作。即,它是类中的一个方法。
  • 目标(Target):被通知对象。
  • 代理(Proxy):向目标对象应用通知之后创建的对象。
  • 切入点(PointCut):切面通知执行的“地点”的定义。
  • 连接点(JointPoint):与切入点匹配的执行点。

SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:

即AOP在不改变原有代码的情况下,去增加新的功能。

11.3、使用Spring实现Aop

【重点】使用AOP织入,需要导入依赖包


    org.aspectj
    aspectjweaver
    1.9.7

方式一: 使用Spring的API接口【主要是SpringAPI接口实现】
  1. 在service包下,定义UserService业务接口和UserServiceImpl实现类
package com.hjf.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}
package com.hjf.service;
public class UserServiceImpl implements UserService{
    @Override
    public void add() {
        System.out.println("增");
    }
    @Override
    public void delete() {
        System.out.println("删");
    }
    @Override
    public void update() {
        System.out.println("改");
    }
    @Override
    public void query() {
        System.out.println("查");
    }
}
  1. 在log包下,定义我们的增强类,一个Log前置增强和一个AfterLog后置增强类
package com.hjf.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    @Override
//    returnValue:返回值
    public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为:"+returnValue);
    }
}
package com.hjf.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {

//    method:要执行的目标对象的方法
//    args:参数
//    target:目标对象
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {

        System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");

    }
}
  1. 最后去spring的文件中注册 , 并实现aop切入实现 , 注意导入约束,配置applicationContext.xml文件
<?xml version="1.0" encoding="UTF-8"?>
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       https://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/context
       https://www.springframework.org/schema/context/spring-context.xsd
       http://www.springframework.org/schema/aop
       https://www.springframework.org/schema/aop/spring-aop.xsd">

    
    
    



    

        


        
        
    

测试

import com.hjf.service.UserService;
import com.hjf.service.UserServiceImpl;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyText {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//        动态代理代理的是接口
        UserService userService = context.getBean("userService", UserService.class);
        userService.add();
    }
}
方式二:使用自定义类来实现【主要是切面定义】
  1. 在diy包下定义自己的DiyPointCut切入类
package com.hjf.diy;

public class DiyPiontCut {
    public void before(){
        System.out.println("==方法执行前===");
    }
    public void after(){
        System.out.println("==方法执行后===");
    }
}
  1. 去spring中配置文件

    
    
    

        
            
            

            
            
        
    
  1. 测试:和前面一样
方式三:注解实现Aop
  1. 在diy包下定义注解实现的AnnotationPointCut增强类
//方式三:使用注解方式实现Aop
@Aspect   //标注类是切面
public class AnnotationPointCut {
    @Before("execution(* com.hjf.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("方法执行前");
    }
    @After("execution(* com.hjf.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("方法执行后");
    }

    @Around("execution(* com.hjf.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕前");
        Object proceed = jp.proceed();  //执行方法
        System.out.println("环绕后");
    }
}
  1. 在Spring配置文件中,注册bean,并增加支持注解的配置。

    

    
  1. 测试,和上面一样,不需要改变

12.整合Mybatis

步骤:

  1. 导入相关jar包
    • Junit
    • mybatis
    • mysql数据库
    • spring相关的
    • aop织入
    • mybatis-spring【new】

        
            junit
            junit
            4.13
        
        
            mysql
            mysql-connector-java
            8.0.26
        
        
            org.mybatis
            mybatis
            3.5.7
        
        
            org.springframework
            spring-webmvc
            5.3.10
        

        
            org.springframework
            spring-jdbc
            5.3.10
        
        
            org.aspectj
            aspectjweaver
            1.9.7
        
        
        
            org.mybatis
            mybatis-spring
            2.0.6
        

    

编写配置文件

测试

12.1回顾mybatis
  1. 编写实体类
public class User {
    private int id;
    private String name;
    private String pwd;
  1. 编写核心配置文件
<?xml version="1.0" encoding="UTF-8" ?>
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

    
    
        
    





















  1. 编写接口
public interface UserMapper {
    public List selectUser();
}
  1. 编写mapper.xml
<?xml version="1.0" encoding="UTF-8" ?>
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">


    

  1. 测试
 @Test
    public void test() throws Exception {
       String resource = "mybatis-config.xml";
       InputStream in = Resources.getResourceAsStream(resource);
       SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(in);
       SqlSession sqlSession = sessionFactory.openSession(true);

       UserMapper mapper = sqlSession.getMapper(UserMapper.class);
       List userList = mapper.selectUser();
       for (User user : userList) {
           System.out.println(user);
       }
   }
12.2Mybatis-spring(两种方式)

方式一:

  1. 编写数据源配置

    
        
            
            
            
            
        
    
  2. sqlSessionFactory


    
        

        
        
    
  1. sqlSessionTemplate

    

        
    
  1. 给接口加实现类
public class UserMapperImpl implements UserMapper{
    //我们的所有操作,都使用sqlSession来执行,在原来,现在都使用SqlSessionTemplate;
    private SqlSessionTemplate sqlSession;

    public void setSqlSession(SqlSessionTemplate sqlSession) {
        this.sqlSession = sqlSession;
    }

    @Override
    public List selectUser() {
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();
    }
}
  1. 将写的实现类,注入到spring中

        
    
  1. 测试
 @Test
    public void test(){
      ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
      UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
      for (User user : userMapper.selectUser()) {
         System.out.println(user);
      }
   }

方式二:

SqlSessionDaoSupport

package com.hjf.mapper;

import com.hjf.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.support.SqlSessionDaoSupport;

import java.util.List;

public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
    @Override
    public List selectUser() {
       /* SqlSession sqlSession = getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        return mapper.selectUser();*/
        return getSqlSession().getMapper(UserMapper.class).selectUser();
    }
}

sqlSessionFactory


    
        
    

测试

  @Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserMapper userMapper = context.getBean("userMapper2", UserMapper.class);
        for (User user : userMapper.selectUser()) {
            System.out.println(user);
        }
    }

13、声明式事务

1、回顾事务
  • 把一组业务当作一个业务来做;要么都成功,要么都失败
  • 开发中涉及到数据一致性问题
  • 确保完整性和一致性

事务ACID原则:

  • 原子性([Atom](https://so.csdn.net/so/search?from=pc_blog_highlight&q=Atom)icity)
  • 一致性(Consistency)
  • 隔离性(Isolation)
    • 多个业务可能操作同一个资源,防止数据破坏
  • 持久性(Durability)
    • 事务一旦提交,无论系统出现什么问题,之前操作后的数据不会被影响,被持久化的吓到存储器中
2、spring中的事务管理
  • 声明式事务:AOP
  • 编程式事务:需要在代码中,进行事务的管理

为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况下;
  • 如果我们不在spring中去配置声明式事务,就需要在代码中手动配置事务
  • 事务在项目的开发中十分重要,涉及到数据的一致性和完整性问题,不容马虎!