Maven+Spring实现后端开发

发布于:2025-04-04 ⋅ 阅读:(14) ⋅ 点赞:(0)

一、前置知识的介绍

1.Spring

轻量级的 DI / IoC 和 AOP 容器的开源框架

容器的开源框架网址:https://spring.io/projects/spring-framework

作用:可简化管理创建和组装对象之间的依赖关系

将controller----->service------->dao层的依赖配置使用Spring注解来实现自动注入。

2.Spring IOC

Inverse of Control(控制反转)是一种设计思想 将程序中手动创建对象的流程,交由Spring框架来管理,即把创建对象的控制权反转给Spring框架,由Spring统一管理。把spring ioc 当成一个容器,里面存储管理的对象称为Bean

3.DI

Dependency Injection ,依赖注入,动态地将对象某种依赖关系注入到对象之中.

4.Bean属性scope

singleton:单例, 默认值,调用getBean方法返回是同一个对象,spring的IOC容器中只会存在一个该bean。

prototype: 多例,调用getBean方法创建不同的对象,会频繁的创建和销毁对象造成很大的开销。

5.AOP

Aspect Oriented Program 面向切面编程,在不改变原有逻辑上增加额外的功能。

把功能分两个部分,核心关注点(业务的主要功能)与横切关注点(非核心、额外增加的功能)

通知 Advice:在特定的切入点上执行的增强处理;类型包括@Before前置通知-在执行目标方法之前运行,@After后置通知、@AfterReturning返回通知-在目标方法正常返回值后运行、@AfterThrowing异常通知-在目标方法出现异常后运行、@Around环绕通知-在目标方法完成前、后做增强处理 。

连接点 JointPoint:业务流程在运行过程中需要插入切面的具体位置

切入点 Pointcut:通过特定的规则来筛选连接点, 就是Pointcut,选中那几个你想要的方法

切面 Aspect:定义了切入点+通知的一个类 。

目标 target:目标类,真正的业务逻辑。

织入 Weaving:把切面(某个类)应用到目标函数的过程称为织入。

AOP代理:对AOP框架创建对象的加强,主要有JDK动态代理与CGLIB代理

//目标类 VideoOrderService; 里面每个方法都是连接点(addOrder,findOrderById,delOrder,updateOder);

//切入点是CUD类型的方法,R读取的不作为切入点 ,CRDU全称:增加(Create)、读取查询(Retrieve)、更新(Update)和删除(Delete)

//目标类

VideoOrderService{

//新增订单

addOrder(){ }

//查询订单

findOrderById(){}

//删除订单

delOrder(){}

//更新订单

updateOrder(){} }

//权限切面类 = 切入点+通知

PermissionAspects{

//切入点 定义了什么地方

@Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")

public void pointCut(){}

//before 通知 表示在目标方法执行前切入, 并指定在哪个方法前切入

//什么时候,做什么事情

@Before("pointCut()") public void permissionCheck(){

System.out.println("在 xxx 之前执行权限校验"); } .... }

//日志切面类 = 切入点+通知 LogAspect{

//切入点 定义了什么地方 @Pointcut("execution(public int net.xdclass.sp.service.VideoOrderService.*(..))")

public void pointCut(){}

//after 通知 表示在目标方法执行后切入, 并指定在哪个方法前切入

//什么时候,做什么事情

@After("pointCut()") public void logStart(){

System.out.println("在 xxx 之后记录日志"); } .... }


6.切入点表达式

格式

execution(访问修饰符 返回值类型 包和类 方法

7.代理

创建代理对象来控制对原对象,通过代理类这中间一层,能有效控制对委托类对象的直接访问

静态代理-由程序创建或特定工具自动生成源代码;

动态代理-在程序运行时,运用反射机制动态创建而成,主要有JDK动态代理与CGLIB代理。 

二、搭建项目

1.快速上手搭建

创建maven项目

添加maven依赖可参照网站:https://mvnrepository.com/

在pom.xml中添加依赖

  <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.2.5.RELEASE</version>
        </dependency>

开发实体层(domain)

package net.xdclass.sp.domain;

public class Video {

    private int id;

    private String title;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }
}

创建配置文件

applicationContext.xml:添加bean配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       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">


    <bean name="video" class="net.xdclass.sp.domain.Video" scope="prototype">
            <property name="name" value="tom"/>
            <property name="id" value="23"/>
    </bean>

</beans>

开发启动类

获取bean,调用对象中的方法

package net.xdclass.sp;

import net.xdclass.sp.domain.Video;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

    public static void main(String [] args){

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");

        Video  video = (Video)applicationContext.getBean("video");

        System.out.println(video.getTitle());

    }

}

三、spring的使用介绍

1.使用xml配置 

Bean对象的常见注入方式

作用范围通过scope来指定,singleton-单例, 默认值;prototype:-多例

使用set方法注入

<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton">

        <property name="id" value="9"/>
        <property name="title" value="Spring 5.X课程" />

</bean>

使用带参的构造函数注入

<bean id="video" class="net.xdclass.sp.domain.Video" >

        <constructor-arg name="title" value="面试专题课程第一季"></constructor-arg>

</bean>

POJO类型注入(property 没有使用value属性,而是使用了ref属性)

<bean id="video" class="net.xdclass.sp.domain.Video" >

        <constructor-arg name="title" value="面试专题课程第一季"></constructor-arg>

    </bean>


    <bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" >
        <property name="id" value="8" />
        <property name="outTradeNo" value="23432fnfwedwefqwef2"/>
        <property name="video" ref="video"/>
    </bean>

 list类型与Map类型的注入

<bean id="video" class="net.xdclass.sp.domain.Video" >

        <!--list类型注入-->
        <property name="chapterList">
            <list>
                <value>第一章SpringBoot</value>
                <value>第二章Mybatis</value>
                <value>第三章Spring</value>
            </list>
        </property>

        <property name="videoMap">
            <map>
                <entry key="1" value="SpringCloud课程"></entry>
                <entry key="2" value="面试课程"></entry>
                <entry key="3" value="javaweb课程"></entry>
            </map>
        </property>
</bean>

在实体类中添加返回方法

public class Video {

    private int id;

    private String title;


    private List<String> chapterList;


    private Map<Integer,String> videoMap;

//省略set get方法
}

优化配置

两个类之间大多数的属性都相同,可通过parent标签来避免重复配置

<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton">

        <property name="id" value="9"/>
        <property name="title" value="Spring 5.X课程" />

</bean>


<bean id="video2" class="net.xdclass.sp.domain.Video2" scope="singleton" parent="video">

         <!--只需要配置不同的属性即可-->
        <property name="summary" value="这个是summary"></property>

</bean>

 两个类之间存在属性依赖,可通过depend-on实现实例化的顺序

<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton">

        <property name="id" value="9"/>
        <property name="title" value="Spring 5.X课程" />

</bean>

<!--设置两个bean的关系,video要先于videoOrder实例化-->

<bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" depends-on="video">
        <property name="id" value="8" />
        <property name="outTradeNo" value="23432fnfwedwefqwef2"/>
        <property name="video" ref="video"/>
</bean>

Bean生命周期

通过init-method与destroy-method来指定

<bean id="video" class="net.xdclass.sp.domain.Video" scope="singleton" init-method="init" destroy-method="destroy">

自动装配属性autowire

可为一个 bean 定义指定自动装配模式,可设置的值有no-不开启、byName-据id注入对应属性、byType-据类型注入属性、constructor-据构造函数注入属性。

<bean id="videoOrder" class="net.xdclass.sp.domain.VideoOrder" autowire="byName">

 2.使用注解配置

开启注解的配置

package net.xdclass.sp;

import net.xdclass.sp.aop.AnnotationAppConfig;
import net.xdclass.sp.domain.Video;
import net.xdclass.sp.domain.VideoOrder;
import net.xdclass.sp.service.VideoService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App {

    public static void main(String[] args) {

        //1.加载注解配置类
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AnnotationAppConfig.class);

        //2.通过@Component获取bean
        VideoService videoService = (VideoService) context.getBean("videoService");

        //3.调用Bean对象的业务方法
        videoService.findById(2);

    }


}
  • 配置Bean对象

通过@Component("Bean对象名") 通用组件 细分: @Controller (用于web层) @Service (用于service层) @Repository (用于dao仓库层)

domain层

package net.xdclass.sp.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;

@Component
public class Video {

    private int id;

    private String title;


    public void init(){
        System.out.println("video类 init 方法被调用");
    }


    public void destroy(){
        System.out.println("video类 destroy 方法被调用");
    }


    public Video(){

        //System.out.println("video 空构造函数被调用");

    }

    public Video(String title){
        //System.out.println("video 带参数构造函数被调用");
        this.title = title;
    }


    public int getId() {
        return id;
    }

    public void setId(int id) {
        //System.out.println("Video setId方法被调用");
        this.id = id;
    }

    public String getTitle() {
        return title;
    }


    public void setTitle(String title) {

        //System.out.println("Video setTitle方法被调用");
        this.title = title;
    }
}

controller层:未指定时,默认为方法名 + 第一个字母小写 作为bean的名称

package net.xdclass.sp.controller;

import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;

@Controller
public class VideoController {
}

service层

package net.xdclass.sp.service;

import net.xdclass.sp.config.CustomConfig;
import net.xdclass.sp.dao.VideoDao;
import net.xdclass.sp.domain.Video;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

//@Component("videoService")
@Service("videoService")
public class VideoServiceImpl implements VideoService {


    @Autowired//实现Bean对象的注入
    private VideoDao videoDao;


    @Autowired
    private CustomConfig customConfig;


    public int save(Video video) {

        System.out.println("保存video");


        return 1;
    }

    public Video findById(int id) {

        System.out.println("根据id找视频");
        videoDao.test();

        System.out.println(customConfig.getHost());

        try {
            Thread.sleep(2000L);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return new Video();
    }
}

dao层

package net.xdclass.sp.dao;

import org.springframework.stereotype.Repository;

@Repository("videoDao")
public class VideoDao {


    public void test(){
        System.out.println("video Dao test ");
    }

}
  • 注入Bean对象 

类型注入@Autowired;名称注入@Qualifier

bean生命周期

@PostConstruct初始化、@PreDestroy销毁

bean作用范围

@scope注解,singleton-单例, 默认值;prototype:-多例

package net.xdclass.sp.domain;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.List;
import java.util.Map;

@Component
//@Scope("prototype")
@Scope
public class Video {

    private int id;

    private String title;


    @PostConstruct
    public void init(){
        System.out.println("video类 init 方法被调用");
    }


    @PreDestroy
    public void destroy(){
        System.out.println("video类 destroy 方法被调用");
    }
   
}

定义第三方bean

@Configuration标注在类为spring容器(相当于类在spring的xml配置文件中的配置)

@bean标注方法为一个Bean对象,将Bean对象交给Spring管理,Spring将Bean对象放入IOC容器中。

注意:bean都需要在@Configuration注解下进行创建

package net.xdclass.sp.config;

import net.xdclass.sp.domain.VideoOrder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

@Configuration
public class AppConfig {


    //使用@bean注解,表明这个bean交个spring 进行管理
    // 如果没有指定名称,默认采用 方法名 + 第一个字母小写 作为bean的名称
    @Bean(name = "videoOrderName",initMethod = "init",destroyMethod = "destroy")
    @Scope
    public VideoOrder videoOrder(){
        return new VideoOrder();
    }

}

自动映射配置文件

@PropertySource,指定加载配置文件,实现将配置文件映射到实体类;

@Value映射到具体的java属性

创建配置文件config.properties


server.host=127.0.0.1

server.port=999

映射到实体类中

package net.xdclass.sp.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration//1.指定这个类是一个配置类
@PropertySource(value = {"classpath:config.properties"})//2.指定配置文件
public class CustomConfig {

    @Value("${server.host}")//3.注入配置文件中的属性值
    private String host;

    @Value("${server.port}")
    private int port;

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }
}

 四、事务管理

1.概念

多个操作,要么同时成功,要么失败后一起回滚。包括A(Atomic-原子性)C(Consistency-一致性)I(Isolation-隔离性)D(Durability-持久性)四种特性.

2.方法

beginTransaction()、commit()、rollback()

3.事务传播

在开始当前事务之前,一个事务上下文已经存在,实现指定一个事务性方法的执行行为

4.事务隔离

是指若干个并发的事务之间的隔离程度