栏目分类:
子分类:
返回
终身学习网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
终身学习网 > IT > 软件开发 > 后端开发 > Java

狂神说spring

Java 更新时间:发布时间: 百科书网 趣学号
狂神说spring
1.spring 1.1 简介
  • spring:春天

  • 2002年,首次推出了spring框架的雏形: interface21框架

  • spring框架以inferface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版

  • spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架

  • ssh:struct2+spring+hibernate

  • SSM:springmvc+spring+mybatis

spring官网

GitHub:https://github.com/spring-projects/spring-framework

spring maven依赖


    org.springframework
    spring-webmvc
    5.2.0.RELEASE




    org.springframework
    spring-jdbc
    5.2.0.RELEASE

1.2 优点
  • spring是一个开源的免费的框架
  • 轻量级的非入侵式的框架
  • 控制反转(IOC)和面向切面编程(AOP)
  • 支持事务处理,对框架整合的支持

spirng就是一个轻量级的控制反转(IOC)和面向切面编程的框架(AOP)

1.3 组成

七大模块

1.4 拓展

现在的java开发,说白了就是基于java开发

  • springboot
    • 一个快速开发的框架
    • 基于springboot可以快速开发单个微服务
    • 约定大于配置
  • springcloud
    • springcloud是基于springboot实现的
  • springsecurity
    • 安全控制

现在大多数公司都在使用springboot进行快速开发,学习springboot的前提是完全掌握spring和springmvc!

弊端:发展了太久之后,违背了原来的理念!配置十分繁琐.

2.IOC理论
  • 原来的过程
    • 接口
    • 实现类
    • 业务接口
    • 业务实现类
private UserDao userDao = new UserDaoImpl();

UserDao每多一个功能实现类,我们都需要调整底层code

在之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求改源代码!如果程序代码量很大,成本会十分昂贵!

我们使用一个set接口实现(已经发生了革命性的变化)

public void setUserDao(UserDao userdao) {
    this.userDao = userdao;
}
  • 之前程序是主动创建对象!控制权在程序员手上!
  • 使用了set注入后,程序不再具有主动性,而是变成了被动的接收对象.
  • 这就是控制反转

这种思想从本质上解决了问题,程序员不用再去管理对象的创建了.系统的耦合性大大降低了,可以更加专注的在业务的实现上.这是IOC的原型

之前和使用set注入之后

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iSJ3R8in-1632825335663)(狂神说spring.assets/image-20210918153443536.png)]

2.1 IOC本质

IOC是一种设计思想,DI是IOC的一种实现方式

所谓控制反转,就是**获得依赖对象的方式反转了**

IOC是spring框架的核心内容

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

3.HelloSpring 3.1 测试样例
  • pojo
package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Hello {
    private String name;
}
  • beans.xml



    
    
        
    


  • test
@Test
public void test01(){
    
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    
    Hello hello = (Hello) context.getBean("hello");
    System.out.println(hello);
}

问题

  • hello对象是谁创建的?

spring

  • hello对象的属性是怎么设置的

spring容器设置的

这个过程就叫控制反转

  • 控制:传统应用程序的对象是由程序本身创建的,使用spring之后,对象是spring创建的
  • 反转:程序本身不创建对象,变成了被动接受对象
  • 依赖注入:就是利用set方法来进行注入的

IOC是一种编程思想,由主动的编程变成被动的接收.

所谓IOC:对象由spring来创建,管理,装配.

4.IOC创建对象的方式
  • 使用无参构造方法创建对象,默认!

  • 假设我们使用有参来构造

    • 下标赋值
    
        
        
        
    
    
    • 类型赋值
    
        
        
    
    
    • 直接通过参数名来设置
    
        
        
    
    

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

5.spring配置 5.1 别名

    



通过bean本来的名字和别名都能获取到对象


alias中的name取注册过的bean的id

5.2 Bean配置

    

  • id:bean的唯一标识符,也就是相当于对象名
  • class:bean对象所对应的全限定名
  • name:起别名,而且同时取多个别名(多个别名时可以用 逗号or空格or分号 分割)
5.3 import

一般用于团队开发使用,它可以将多个配置文件,导入合并为一个

假设现在项目中由多人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以用import将所有人的beans.xml合并为一个总的!




使用的时候直接使用总的配置文件就可以了

6.依赖注入 6.1 构造器注入

前面说过了


    
    

6.2 Set方式注入[重点]
  • 依赖注入:Set注入!
    • 依赖:bean对象的创建依赖于容器!
    • 注入:bean对象种的所有属性,由容器来注入!

[环境搭建]

  • 复杂类型
package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Address {
    private String address;
}

  • 真实测试对象
package pojo;

import com.sun.xml.internal.ws.api.ha.StickyFeature;
import javafx.scene.effect.SepiaTone;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;

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

  • beans.xml




  • 完善注入信息




    
        
    

    
        
        
        
        
        
        
            
                红楼梦
                西游记
                水浒传
                三国演义
            
        
        
        
            
                睡觉
                写代码
                看电影
            
        
        
        
            
                
                
            
        
        
        
            
                tokens
                COC
            
        
        
        
            
        
        
        
            
                1
                3
            
        
    


  • 测试类
package demo;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import pojo.Address;
import pojo.Student;

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);
    }
}
  • 结果

6.3 拓展方式注入

不能直接使用,需要导入然后再进行使用

  • p命名空间注入



    
    
    



  • c命名空间注入


    
    
    



6.4 bean的作用域
ScopeDescription
singleton(Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototypeScopes a single bean definition to any number of object instances.
requestScopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. only valid in the context of a web-aware Spring ApplicationContext.
sessionScopes a single bean definition to the lifecycle of an HTTP Session. only valid in the context of a web-aware Spring ApplicationContext.
applicationScopes a single bean definition to the lifecycle of a ServletContext. only valid in the context of a web-aware Spring ApplicationContext.
websocketScopes a single bean definition to the lifecycle of a WebSocket. only valid in the context of a web-aware Spring ApplicationContext.
  • 单例模式,默认就是单例模式
  • 原型模式:每次从容器中get的时候都会产生一个新对象

  • 其余的request,session等,这些只能在web开发中用到.
7.bean的自动装配
  • 自动装配bean是spring满足bean依赖的一种方式
  • spring会在上下文中自动寻找,并自动给bean装配属性!

在spring中三种装配的方式

  • 在xml中显示配置
  • 在java中显示配置
  • 隐式的自动装配bean[重要]
7.1 测试
  • 环境搭建(一个人有两只宠物)
7.2 ByName自动装配

    

byname的时候,需要保证所有bean的id唯一,并且这个bean的id需要和自动注入bean的属性的set方法中名称一致

7.3 ByType自动装配







    

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

7.4 使用注解实现自动装配

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

要用注解,须知

  • 导入约束 context约束
xmlns:context="http://www.springframework.org/schema/context"
  • 配置注解的支持




    


注解

  • @Autowired
    • 直接在属性上使用即可
    • 可以在set方法上用
    • 使用autowired我们可以不用编写set方法,前提是自动装配的属性在ioc容器中存在,且符合名字byname

@Nullable 字段标记了这个注解,说明这个字段可以为null

public @interface Autowired {
    boolean required() default true;
}
@Autowired(required = false)

说明这个对象可以为null,否则不能为null

@Qualifier(value = "xxx")

当属性在ioc容器中存在多个的时候,可以用该注解来指定注入的bean,xxx为对应bean的id

@Resource注解

package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {

    @Resource(name = "cat")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog")
    private Dog dog;
    private String name;
}

小结:@Resource和 @Autowired的区别

  • 都是用来自动装配的,都可以放在字段上
  • @Autowired先通过bytype方式来实现,然后通过byname,而且必须要求对象存在
  • @Resource默认通过byname来实现,如果找不到名字,则通过bytype来实现!如果都找不到就报错
8.使用注解开发

在spring4之后,要使用注解开发,必须要保证aop的包导入了

使用注解需要导入context包,增加注解的支持




    


    

8.1 bean 8.2 属性注入
package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
    // 相当于property赋值
    @Value("kuquan")
    private String name;
}



8.3 衍生的注解

@Component有几个衍生注解,在web开发中,会按照mvc三层架构分层

  • dao [@Repository]
  • service [@Service]
  • controller [@Controller]

这四个注解功能是一样的,都是把某个类注册到spring容器中,装配bean

8.4 自动装配
package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class People {

    @Resource(name = "cat")
    private Cat cat;
    @Autowired
    @Qualifier(value = "dog")
    private Dog dog;
    private String name;
}
8.5 作用域
@Scope("prototype")
public class User {
    // 相当于property赋值
    @Value("kuquan")
    private String name;
}
8.6 小结

xml与注解

  • xml更加万能,适用于任何场合!维护简单方便
  • 注解,不是自己的类用不了,维护相对复杂!

xml与注解最佳实践

  • xml用来管理bean
  • 注解只负责属性的注入
  • 我们在使用的过程中,只需要注意一个问题,我们必须要注解生效,需要扫描包


9.使用java方式配置spring

完全不使用spring的xml配置,全权交给java来做

javaConfig是spring的一个子项目,在spring4之后成为了一个核心功能

实体类

package pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Data
@AllArgsConstructor
@NoArgsConstructor
@Component
public class User {
    @Value("kuquan")
    private String name;
}

package config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScans;
import org.springframework.context.annotation.Configuration;
import pojo.User;


@Configuration
@import(xxx.class)
public class AppConfig {

    
    @Bean
    public User getUser(){
        return new User();
    }
}
package demo;

import config.AppConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import pojo.User;

public class MyTest {
    @Test
    public void test01(){
        
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user);
    }
}

这种纯java在springboot中随处可见.

10.代理模式

为什么要学习代理模式呢?

因为这就是spring的AOP底层.

代理模式的分类

  • 静态代理
  • 动态代理

10.1 静态代理

角色分析

  • 抽象角色:一般使用抽象类或者接口来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后.我们一般会做一些附属操作
  • 客户:访问代理对象的人

代码步骤

  • 接口
public interface Rent {
    public void rent();
}
  • 真实角色
package kuquan.demo1;


public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("房东要出租房子");
    }
}

  • 代理角色
package kuquan.demo1;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Proxy implements Rent{

    private Host host;


    @Override
    public void rent() {
        seeHouse();
        host.rent();
        hold();
        getMoney();
    }

    
    public void seeHouse(){
        System.out.println("中介带你看房");
    }

    
    public void hold(){
        System.out.println("签合同");
    }

    
    public void getMoney(){
        System.out.println("收中介费");
    }
}

  • 客户端访问
package kuquan.demo1;

public class Client {
    public static void main(String[] args) {
        // 房东租房子
        Host host = new Host();
        // 代理,中介帮房东租房子,但是呢?代理一般有一些附属操作
        Proxy proxy = new Proxy(host);
        // 你不用面对房东,直接找中介租房即可
        proxy.rent();
    }
}

代理模式的好处

  • 可以使得真实角色的操作更加纯粹!不用再去关注一些公共的业务
  • 公共也就交给了代理!实现了业务分工!
  • 公共业务发生拓展的时候方便集中管理

缺点

  • 一个真实的角色就会产生一个代理角色,代码量翻倍,开发效率变低
10.2 静态代理再理解

样例:08-demo2

10.3 动态代理
  • 动态代理和静态代理的角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理;基于类的动态代理
    • 基于接口:jdk代理
    • 基于类:cglib
    • java字节码实现:javasist

需要了解两个类:Proxy(代理), InvocationHandler:调用处理程序

动态代理的好处:

  • 可以使得真实角色的操作更加纯粹!不用再去关注一些公共的业务
  • 公共也就交给了代理!实现了业务分工!
  • 公共业务发生拓展的时候方便集中管理
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类,可以带多个类,只要是同一个接口即可

动态代理通用类

package kuquan.demo4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


@Data
@AllArgsConstructor
@NoArgsConstructor
public class proxyInvocationHandler implements InvocationHandler {

    
    private Object target;

    
    public Object getProxy(){
        Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
        return o;
    }

    
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        

        
        Object result = method.invoke(target, args);

        

        return result;
    }
    
    
    
}

11.AOP 11.1 什么是AOP?

在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

11.2 AOP在spring中的应用

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

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

11.3 使用spring实现AOP

AspectJ织入


    org.aspectj
    aspectjweaver
    1.9.4


方式一:使用spring的API接口

注册aop和注释的配置文件




    

    
    
        
        

        
        
        

    


方式二:使用自定义类来实现AOP[主要是切面]

这种方式比较简单,但是功能也比较弱

package kuquan.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("方法执行前");
    }

    public void after(){
        System.out.println("方法执行后");
    }
}

xml




    

    
    

    

    

    
    

    
        
        
            
            
            
            
            
        
        
    


方式三:使用注解实现

package kuquan.diy;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;


@Aspect
public class AnnotationPointCut {
    @Before("execution(* kuquan.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("before");
    }
}

// 然后再ioc容器中注册bean即可
12.整合Mybatis

步骤

  • 导入相关的jar包
    • junit
    • mybatis
    • mysql数据库
    • spring相关
    • aop织入
    • mybatis-spring[new]
  • 编写配置文件
  • 测试

依赖


    mysql
    mysql-connector-java
    5.1.35



    org.mybatis
    mybatis
    3.5.2




    org.springframework
    spring-jdbc
    5.1.9.RELEASE




    org.mybatis
    mybatis-spring
    2.0.6

12.1 回忆mybatis

编写实体类

编写核心配置文件

编写接口

编写mapper.xml

测试

12.2 mybatis-spring

mybatis-spring

  • 编写数据源配置

    
    
    
    

  • 创建sqlSessionFactory

    
    
    

  • 创建SqlSessionTemplate

    
    

  • 将这部分剥离出来单独作为spring-dao.xml

  • 与mybatis不同的是,我们需要给mapper一个实现类

package kuquan.mapper;

import kuquan.pojo.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

public class UserMapperImpl implements UserMapper{

    
    @Autowired
    private SqlSessionTemplate sqlSession;

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

    @Override
    public List selectAll() {
        return sqlSession.getMapper(UserMapper.class).selectAll();
    }
}

然后将其注入ioc容器中(参数使用注解的方式注入了)


测试

@Test
public void test03(){
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    // 注入传入的是userMapper接口的实现类的id,然后传入UserMapper的class
    UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
    List userList = userMapper.selectAll();

    for (User user : userList) {
        System.out.println(user);
    }
}
13.声明式事务 13.1 事务

把一组业务当作一个业务来做;要么都成功,要么都失败

要么都成功,要么都失败

事务在项目开发中,十分重要,涉及到数据一致性问题!不容马虎!

保证完整性和一致性

13.2 事务的ACID原则
  • 原子性
  • 一致性
  • 隔离性
    • 多个业务可能操作同一个资源,要保证业务是相互隔离的,防止数据损坏
  • 持久性
    • 事务一旦提交,无论系统发生什么问题,结果都不会被印象,都被持久化地写到存储器中
13.3 spring中的事务管理
  • 声明式事务:AOP

  • 编程式事务:需要在代码中进行事务的管理

  • spring中开启事务


    

  • 通过AOP方式实现事务织入


    
    
    
        
        
        
        
        
    

  • 配置事务切入

	
	

这样就在不修改代码的情况下添加了事务

思考:为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况

  • 如果我们不在spring中配置声明式事务,就需要在代码中手动配置
    apper userMapper = context.getBean(“userMapper”, UserMapper.class);
    List userList = userMapper.selectAll();

    for (User user : userList) {
    System.out.println(user);
    }
    }





## 13.声明式事务

### 13.1 事务

> 把一组业务当作一个业务来做;要么都成功,要么都失败
>
> 要么都成功,要么都失败
>
> 事务在项目开发中,十分重要,涉及到数据一致性问题!不容马虎!
>
> 保证完整性和一致性



### 13.2 事务的ACID原则

* 原子性
* 一致性
* 隔离性
  * 多个业务可能操作同一个资源,要保证业务是相互隔离的,防止数据损坏
* 持久性
  * 事务一旦提交,无论系统发生什么问题,结果都不会被印象,都被持久化地写到存储器中



### 13.3 spring中的事务管理

* 声明式事务:AOP
* 编程式事务:需要在代码中进行事务的管理



* spring中开启事务

```xml


    

  • 通过AOP方式实现事务织入


    
    
    
        
        
        
        
        
    

  • 配置事务切入

	
	

这样就在不修改代码的情况下添加了事务

思考:为什么需要事务?

  • 如果不配置事务,可能存在数据提交不一致的情况
  • 如果我们不在spring中配置声明式事务,就需要在代码中手动配置
  • 事务在项目开发中十分重要,涉及到数据完整性和一致性
转载请注明:文章转载自 www.051e.com
本文地址:http://www.051e.com/it/276524.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 ©2023-2025 051e.com

ICP备案号:京ICP备12030808号