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

Spring

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring

文章目录
    • 1.Spring简介
      • 1.1简介
      • 1.2优点、
      • 1.3、spring的组成
      • 1.4拓展
          • Spring Boot
          • SpringCloud
          • 弊端:
    • 2、IOC理论推导
      • 传统:
      • 依赖反转
      • IOC本质
    • 3.HellpSpring
      • 1、spring创建对象
        • 1.创建一给实体类hello
        • 2.编写beans.xml文件
        • 3.测试
    • 4、IOC创建对象的方式
      • 1、使用无参构造创建对象
      • 2、使用有参构造创建对象
        • 1、下标赋值
        • 2、类型赋值
        • 3、参数名赋值
    • 5、Spring配置说明
      • 1、别名
      • 2、beans的配置
      • 3、import
    • 6、DI依赖注入
      • 6.1、构造器注入
      • 6.2、set方式注入【重点】
      • 6.3、拓展方式注入
    • 7、Beans作用域
      • 1、单例模式(默认,只有一个)
      • 2、原型模式(每次从容器中get时,都会产生一个对象)
    • 8、Bean自动装配
        • spring的三种配置方式
      • 8.1测试
      • 8.2、byName自动装配
      • 8.3byType自动装配
      • summary
    • 9、使用注解自动装配【bean.xml更新1.0】
      • 1、**注解须知:**
      • 2、@**Autowired:**
      • 3、@Qualifier
      • 4、@Resource
      • summary:
    • 10、spring使用注解开发
      • 1.bean
      • 2.属性如何注入
      • 3.衍生的注入
      • 4.自动装配配置
      • 5.作用域
      • 6.小结
    • 11、基于javaConfig实现配置spring(注解)
      • 配置
        • 实体类
      • 测试
    • 11、代理模式
      • 10.1、静态代理
      • 10.2、加深理解
      • 10.3、动态代理
    • 13、AOP(面向切面编程)
      • 13.1、什么是AOP
      • 13.2、AOP在Spring中的作用
      • 11.3、使用Spring实现AOP
        • 方式一:使用SpringAPI接口【主要是springAPI】
          • **2.创建一个要增加的功能的名字(log)的包,在包里添加各种方法**
          • 3.spring配置,bean的注册
          • 方式一:使用原生的springAPI开发
          • 4.测试
        • 方式二:使用自定义类【主要是切面定义】
        • 方式三、使用注解开发
    • 14、整合Mybatis
      • 14.1、回忆mybatis
      • 14.3、Mybatis-Spring
    • 15、声明式事务
      • 1、回顾事务

1.Spring简介 1.1简介
  • Spring:春天
  • Spring框架是由于软件开发的复杂性而创建的。
  • Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。
    • 轻量——从大小与开销两方面而言Spring都是轻量的
    • 控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。
    • 面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。
    • 容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,
    • 框架——Spring可以将简单的组件配置、组合成为复杂的应用。

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

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

官方下载地址https://repo.spring.io/ui/native/release/org/springframework/spring/

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



    org.springframework
    spring-webmvc
    5.3.10




    org.springframework
    spring-jdbc
    5.3.10


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

Summary

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

1.3、spring的组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9V7pxYE6-1651656883855)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716046.png)]

每个模块的作用如下:

  1. 核心容器(Spring Core):核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
  2. Spring 上下文(Spring Context):Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI(Java命名和目录接口)、EJB(Enterprise Java Beans称为Java 企业Bean)、电子邮件、国际化、校验和调度功能。
  3. Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向切面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
  4. Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写 的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
  5. Spring ORM:Spring 框架插入了若干个 ORM (对象关系映射)框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
  6. Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
  7. Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP。
1.4拓展

spring的官网有这个介绍,现代化的java开发!说白了就是基于spring的开发!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NTpgh0yp-1651656883856)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716047.png)]

Spring Boot
  • 一个快速开发的脚手架
  • 基于spring Boot可以快速开发单个微服务
  • 约定大于配置!!

因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握spring和springMVC!承上启下!

SpringCloud
  • springCloud基于springBoot实现的
弊端:

spring发展了太久之后,已经违背了原理!人称:配置地狱

2、IOC理论推导 传统:
  1. userDao接口
package com.kuang.dao;

public interface UserDao {
    //1.方法
    void getUser();
}
  1. userDaoImpl 实现类
package com.kuang.dao;

//实现类
public class UserDaoImpl implements UserDao {

    @Override
    public void getUser() {
        System.out.println("默认的获取用户的数据");
    }
}
  1. userService接口 业务接口
package com.kuang.service;

public interface UserService {
    //1.和userDao一样的方法,相当于这一层调用dao层的方法
    void getUser();
}
  1. userServiceImpl 业务实现类
package com.kuang.service;

import com.kuang.dao.UserDao;
import com.kuang.dao.UserDaoImpl;
import com.kuang.dao.UserDaoMysqlImpl;

public class UserServiceImpl implements UserService{
    //1.引入dao层的userDao

private UserDao userDao;

//控制反转,利用set进行动态值的注入!
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void getUser() {
        userDao.getUser();//业务层调dao层
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dCVu9xHU-1651656883856)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716048.png)]

在之前的业务中,用户的需求可能会影响我们的代码,我们需要根据用户的需求去修改源代码,破坏了程序的完整性,

依赖反转

我们使用一个set接口实现

private UserDao userDao;

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FVxweQ9O-1651656883857)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716049.png)]

这种思想,从本质上解决了问题,不需要再管理对象的创建,全部使用接口编程,系统的耦合性大大降低,可以更加专注在业务的实现上,这是IOC的原型!

IOC本质

控制反转loC(lnversion of Control),是一种设计思想,DI(依赖注入)是实现!oC的一种方法,也有人认为DI只是
Ioc的另一种说法。没有loc的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序
中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖
对象的方式反转了

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uQKem7mk-1651656883857)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716050.png)]

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

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




      
        
    

    
        
    

    

xml
3.HellpSpring 1、spring创建对象 1.创建一给实体类hello
package com.kuang.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 + ''' +
                '}';
    }
}
2.编写beans.xml文件





    
        
    

3.测试
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中被管理了,我们要使用,直接去里面取出来,就可以!
        Object hello = context.getBean("hello");
        System.out.println(hello.toString());

    }
}
  • hello 对象是由谁创建的?
  • hello 对象是由Spring创建的
  • Hello 对象的属性是怎么设置的?
  • hello 对象的属性是由Spring容器设置的,

这个过程就叫控制反转

控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的.

反转:程序本身不创建对象,而变成被动的接收对象.

依赖注入:就是利用set方法来进行注入的.

IOC是一种编程思想,由主动的编程变成被动的接收.可以通过newClassPathxmlApplicationContext去浏览一下底层源码。
OK,到了现在,我们彻底不用再程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的IOC一句话搞定:对象由Spring 来创建,管理,装配!

4、IOC创建对象的方式 1、使用无参构造创建对象

1.创建实体类

package com.kuang.pojo;

public class User {
    private String name;

    //1.默认是通过无参构造,创建对象
    public User(){
        System.out.println("user对象已创建");
    }
    public void setName(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    public void show(){
        System.out.println("name"+name);
    }
}

2.配置beans.xml文件






3.测试

import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class mytest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("User");

    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EJ4qNanA-1651656883857)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716051.png)]

2、使用有参构造创建对象 1、下标赋值



2、类型赋值


    

3、参数名赋值




    

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

5、Spring配置说明 1、别名

区分大小写






    

    




2、beans的配置

    
3、import

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

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

  • 张三
  • 李四
  • 王五
  • applicationContext.xml


    
    
    
    

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

6、DI依赖注入 6.1、构造器注入

前面已经说过

6.2、set方式注入【重点】
  • 依赖注入:Set注入!!
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入!!

环境搭建

  1. 复杂类型
package com.kuang.pojo;

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
}

2.真实测试对象

package com.kuang.pojo;

import java.util.*;

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

3.beansxml




    
        
    



4.测试

import com.kuang.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class mytest {
    @Test
    public void test01() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) context.getBean("student");
        String name = student.getName();
        System.out.println(name);
    }
}

5、




    

        


        
            
                
            
        


        
        
            三国演义
            红楼梦
            水浒传
        
        


        
            
                reading
                listening to music
                playing
            
        


        
            
                LOL
                SC2
                DOTA2
            
        


        
            
                
                
            
        


        
            
        


        
            
                1531132135
                112323
            
        
    

import com.kuang.pojo.Student;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class mytest {
    @Test
    public void test01() {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        Student student = (Student) context.getBean("student");
        String name = student.getName();
        System.out.println(name);

        System.out.println(student.toString());
//        Student{name='qingjian',
//        address=Address{address='china'},
//        books=[三国演义, 红楼梦, 水浒传], 
//        hobbies=[reading, listening to music, playing], 
//        games=[LOL, SC2, DOTA2], 
//        card={银行卡=1531354, 电话号码=155134533},
//        wife='null',
//        info={学号=1531132135, 成绩=112323}}

    }
}
6.3、拓展方式注入

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PjBI6tnC-1651656883858)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716052.png)]

我们可以使用p命名空间和c命名空间进行注入









    

测试:

    @Test
    public void test2(){
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user1 = context.getBean("user1", User.class);
        System.out.println(user1.toString());

        User user2 = context.getBean("user2", User.class);
        System.out.println(user2.toString());
    }
}

注意:必须提前到如约束

   xmlns:p="http://www.springframework.org/schema/p"
   xmlns:c="http://www.springframework.org/schema/c"xml
7、Beans作用域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnCKDGFH-1651656883859)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716053.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1rzTItCm-1651656883859)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716054.png)]

1、单例模式(默认,只有一个)

只有一个单例 bean 的共享实例被管理,并且所有对带有一个或多个 ID 与该 bean 定义匹配的 bean 的请求都会导致 Spring 容器返回一个特定的 bean 实例

2、原型模式(每次从容器中get时,都会产生一个对象)



    

Bean 部署的非单一原型范围导致每次对特定 bean 发出请求时都会创建一个新 bean 实例。

数据访问对象 (DAO) 通常不配置为原型,因为典型的 DAO 不保存任何会话状态。我们更容易重用单例图的核心。

3、其余的request、session、application,都只在web中出现

request:在一次请求

session:一次会话

application:一次应用

8、Bean自动装配
  • 自动装配是spring满足bean依赖的一种方式
  • spring会在上下文中自动寻找,并自动给bean装配属性
spring的三种配置方式
  • 在xml中配置
  • 在java中配置
  • 隐式的自动装配bean==【重要】==
8.1测试

1.环境搭建

  • 一个人有两个宠物




    
        
        
        

        
    

8.2、byName自动装配


    
    


    
        




    

8.3byType自动装配

只能有一个bean,并且可以忽略id设置,只要配置class就行



    
    


    
        
    

summary
  • byName:需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一样。
  • byType:需要保证所有的bean的class唯一,并且这个bean需要和自动注入的属性的类型一样。
9、使用注解自动装配【bean.xml更新1.0】

根据实际情况自己选择是否选择注解装配

1、注解须知:
  1. 导入约束:context约束
  2. 配置注解的支持:context:annotation-config/



        

2、@Autowired:
  • 直接在属性上使用即可!, 也可以在set方式上使用
  • 使用Autowired,可以不用写set方法,前提是自动装配的属性在IOC(spring)容器中存在,且符合名字?类型?byname or bytype
    • 先bytype 再byname
package com.kuang.pojo;

import org.springframework.beans.factory.annotation.Autowired;

public class People {
    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;

    private  String name;

    public Dog getDog() {
        return dog;
    }
    public Cat getCat() {
        return cat;
    }
}
3、@Qualifier

如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解【@Autowired】完成的时候,我们可以使用@Qualifier(value=“xxx”)取配置@Autowired的使用,指定一个唯一的bean对象注入。

package com.kuang.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class People {
    @Autowired
    private Dog dog;
    @Autowired
    @Qualifier(value = "cat1")
    private Cat cat;

    private  String name;

    public Dog getDog() {
        return dog;
    }
    public Cat getCat() {
        return cat;
    }
        @Override
    public String toString() {
        return "People{" +
                "dog=" + dog +
                ", cat=" + cat +
                ", name='" + name + ''' +
                '}';
    }
}
4、@Resource
package com.kuang.pojo;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import javax.annotation.Resource;

public class People {
    @Resource
    private Dog dog;
@Resource
    private Cat cat;
    private  String name;
    public Dog getDog() {
        return dog;
    }
    public Cat getCat() {
        return cat;
    }
        @Override
    public String toString() {
        return "People{" +
                "dog=" + dog +
                ", cat=" + cat +
                ", name='" + name + ''' +
                '}';
    }
}
summary:

@Resource和@Autowired的区别:

  • 都是用来自动装配的,都可以防止属性字段上
  • @Autowired默认通过byType,当匹配到多个同类型时,通过byname进行装配(需要使用@Qualifier)
  • Resource默认通过byname,如果找不到,则通过byType实现!!如果两个都找不到,就报错!
  • 执行循序不同,@Autowired通过byType方式实现。
10、spring使用注解开发

在Spring4之后,要使用注解开发,必须要保证AOP的包的导入!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E4CC4lsN-1651656883861)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716055.png)]

在使用注解要导入context约束,增加注解的支持




        

1.bean

@component

正常创建完一个pojo需要在xml中配置bean


但有了@component,就可以直接在uer类中配置

//@Component 等价于
//@Component 组件		会扫描
@Component
public class User {
    
}

可以不用显示的设置值,使用注解注入

@Value("qingjian1")
public String name;
2.属性如何注入
package com.kuang.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;


//@Component 等价于
//@Component 组件
@Component
public class User {

    // @Value("qingjian1")等价于 
    @Value("qingjian1")
    public String name;
}
3.衍生的注入

    

@component有几个衍生的注解,我们在web开发中,会按照mcv三层架构分层

  • dao 【@Repository】
  • service 【@Service】
  • controller 【@Controller】

这个四个注解功能都是一样的,都是代表将某个类注册到spring中,装配给Bean

4.自动装配配置
- @Autowired默认通过byType,当匹配到多个同类型时,通过byname进行装配(需要使用@Qualifier)
- @Resource默认通过byname,如果找不到,则通过byType实现!!如果两个都找不到,就报错!
- @Nullable  字段标记了这个注解,说明这个字段可以为null
- @resource :自动装配 通过名字—>类型
5.作用域
package com.kuang.pojo;

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


//@Component 等价于
//@Component 组件
@Component
@Scope("prototype")
public class User {

    // @Value("qingjian1")等价于 
    @Value("qingjian1")
    public String name;
}
6.小结

xml与注解:

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

xml与注解最佳实践:

  • xml用来管理bean
  • 注解只负责完成属性的注入
  • 我们在使用过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持!

    
    
11、基于javaConfig实现配置spring(注解)

我们现在要完全不使用spring的xml配置了,全权交给java来做!

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LI6KJgyI-1651656883861)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716056.png)]

配置 实体类
package com.kuang.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//这里这个注解的意思,就是说明这个类被spring接管了,注册到了容器中
@Component//不加也行好像
public class User {
    private String name;

    public String getName() {
        return name;
    }

    @Value("秦疆1")//属性注入值
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                '}';
    }
}

javaConfig

package com.kuang.config;

import com.kuang.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
//1.这个也会被spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Component,代表这个是一个配置类,就和我们之前看的beans.xml一样

@ComponentScan("com.kuang.pojo")//2.扫描包

//3.导入其他的包
@Import(kunagConfig.class)
public class myConfig {
    //注册一个bean,就相当于我们之前写的一个bean标签,id就是这个方法的名字(getUser())
    //class就是这个方法的返回值
    @Bean
    public User user(){
        return new User();//就是返回要注入到bean的对象
    }
}
测试
import com.kuang.config.myConfig;
import com.kuang.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.stereotype.Component;

public class myTest {
    @Test
    public void test01(){
        //如果完全使用了配置类去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载!!
        ApplicationContext context = new AnnotationConfigApplicationContext(myConfig.class);
        User getUser = context.getBean("user", User.class);//方法名等价于变量名
        System.out.println(getUser.getName());
    }
}

这种纯java的配置方式在springBoot中随处可见!!

11、代理模式

为什么要学习代理模式?? 因为这就是springAOP的底层!!【springAOP 和springMVC】

代理模式的分类

  • 静态代理
  • 动态代理

少用继承,多用组合!!

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b3ZrEIuj-1651656883862)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716057.png)]

10.1、静态代理

角色分析:

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

代码步骤

  1. 接口

    package demo01;
    //租房,这个抽象类
    public interface rent {
        public void rent();
    }
    
  2. 真实角色

    package demo01;
    
    //房东,真实角色
    public class Host implements rent {
    
        @Override
        public void rent() {
            System.out.println("房东租房啦!");
        }
    }
    
  3. 代理角色

    package demo01;
    
    //中介,代理角色
    public class proxy {
    private Host host;
    
        public proxy() {
        }
    
        public proxy(Host host) {
            this.host = host;
        }
    
    
        //host的租房
        public void rent(){
            seeHouse();
            host.rent();
            hetong();
            fare();
        }
    
        public void seeHouse(){
            System.out.println("中介带你来看房");
        }
        public  void hetong(){
            System.out.println("中介签租赁合同");
        }
        public void fare(){
            System.out.println("收费中介费");
        }
    }
    
  4. 客户端访问代理角色

    package demo01;
    
    public class client {
        public static void main(String[] args) {
            Host host1=new Host();
    //        host1.rent();
            proxy proxy = new proxy(host1);
            proxy.rent();
        }
    }
    

代理模式的优点:

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

缺点:

  • 一个真实角色就会产生一个代理角色;可能导致代码量翻倍
10.2、加深理解

代码:

AOP

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1t8SY05f-1651656883862)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716058.png)]

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

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

代理模式的优点:

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

代码步骤

  1. 接口

    package demo01;
    //租房,这个抽象类
    public interface rent {
        public void rent();
    }
    
  2. 真实角色

    package demo01;
    
    //房东,真实角色
    public class Host implements rent {
    
        @Override
        public void rent() {
            System.out.println("房东租房啦!");
        }
    }
    
  3. 代理角色(自动生成)

    package demo03;
    
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    public class ProxyInvocationHandler implements InvocationHandler {
    
        //被代理的接口
        private Object rent;
    
        public void setRent(Rent rent) {
            this.rent = rent;
        }
    
        //生成得到的代理类
        public Object getProxy(){
            return    Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this );
        }
    
        //处理代理实例,并返回结果
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //动态代理的本质就是反射
            seeHouse();
            Object result = method.invoke(rent, args);
            fare();
            return result;
        }
    
        public void seeHouse(){
            System.out.println("看房子");
        }
        public void fare(){
            System.out.println("交手续费");
        }
    }
    
    
  4. 客户端访问代理角色

    package demo03;
    
    public class client {
        public static void main(String[] args) {
            //真实角色
            Host host=new Host();
    
            //代理角色:现在没有
            ProxyInvocationHandler pih=new ProxyInvocationHandler();
            //通过调用程序处理角色来处理我们要调用的接口对象!
            pih.setRent(host);
    
            Rent proxy = (Rent) pih.getProxy();//这里的proxy就是动态生成的,我们并没有写!!
            proxy.rent();
    
        }
    }
    
13、AOP(面向切面编程)

什么是AOP:在不改变原有代码的基础上,增加多余的功能!

13.1、什么是AOP

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

  • 我们先回顾一下OOP:Object Oriented Programming,OOP作为面向对象编程的模式,获得了巨大的成功,OOP的主要功能是数据封装、继承和多态。
  • 而AOP是一种新的编程方式,它和OOP不同,OOP把系统看作多个对象的交互,AOP把系统分解为不同的关注点,或者称之为切面(Aspect)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yaYrspOh-1651656883862)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716059.png)]

13.2、AOP在Spring中的作用

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

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MVKfLJm3-1651656883863)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716060.png)]

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

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I2rKA9IL-1651656883863)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716061.png)]

11.3、使用Spring实现AOP

【重点】使用AOP需要导入一个包

    
        org.aspectj
        aspectjweaver
        1.9.4
    

方式一:使用SpringAPI接口【主要是springAPI】

1.先创建一个maven项目,在创建一个service包,里面加入UserServiceImpl实现类和Uservice接口

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r0p6WBHn-1651656883864)(r9ptik78f.hn-bkt.clouddn.com/img/blog202205041716062.png)]

2.创建一个要增加的功能的名字(log)的包,在包里添加各种方法

Logbefore:implements实现MethodBeforeAdvice方法

Logbefore

package com.kuang.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Logbefore 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()+"被执行了");
    }
}

LogAfter

package com.kuang.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class LogAfter implements AfterReturningAdvice {
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结果为"+returnValue);
    }
}
3.spring配置,bean的注册

目的,使用spring1进行开发

注册bean


    
    
    
方式一:使用原生的springAPI开发
        

    

        


        
        

    
4.测试
import com.kuang.service.Uservice;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class myTest {
    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //AOP需要使用接口
        Uservice userServiec = (Uservice) context.getBean("userService");

        userServiec.add();
    }
}
方式二:使用自定义类【主要是切面定义】
package com.kuang.diy;

public class DiyPiontCut {
    public void before(){
        System.out.println("==============================before=================");
    }
    public void after(){
        System.out.println("==============================after=================");
    }
}

    
    

        
            
            
            
            
            

        
    
import com.kuang.service.Uservice;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class myTest {
    @Test
    public void test01(){
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        //AOP需要使用接口
        Uservice userServiec = (Uservice) context.getBean("userService");
        userServiec.add();
    }
}
方式三、使用注解开发


    

    
package com.kuang.diy;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect
public class annotionPointCut {
    @Before("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("*****************方法执行前******************");

    }

    @After("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("============方法执行后");
    }


//   在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点
    @Around("execution(* com.kuang.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
        System.out.println("环绕前");
        Object proceed = proceedingJoinPoint.proceed();//执行方法
        System.out.println("环绕后");


        System.out.println(proceedingJoinPoint.getSignature());
        System.out.println(proceed);
    }
}
14、整合Mybatis

步骤:

  1. 导入相关jar

    • juint
    • mybatis
    • mysql
    • spring
    • aop织入
    • mybatis-spring【新知识点】
        
            
                junit
                junit
                4.12
            
            
                mysql
                mysql-connector-java
                8.0.25
            
            
                org.mybatis
                mybatis
                3.5.2
            
            
                org.springframework
                spring-webmvc
                5.3.10
            
    
            
                org.springframework
                spring-jdbc
                5.3.10
            
            
                org.aspectj
                aspectjweaver
                1.9.4
            
            
                org.mybatis
                mybatis-spring
                2.0.2
            
        
    
  2. 编写配置文件

  3. 测试

14.1、回忆mybatis
  1. 编写实体类

    package com.kuang.pojo;
    
    public class user {
        private int id;
        private String name;
        private String pwd;
    
        public user() {
        }
    
        public user(int id, String name, String pwd) {
            this.id = id;
            this.name = name;
            this.pwd = pwd;
        }
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getPwd() {
            return pwd;
        }
    
        public void setPwd(String pwd) {
            this.pwd = pwd;
        }
    
        @Override
        public String toString() {
            return "user{" +
                    "id=" + id +
                    ", name='" + name + ''' +
                    ", pwd='" + pwd + ''' +
                    '}';
        }
    }
    
    
  2. 编写核心配置文件

    
    
    
    
        
                
        
    
        
            
                
                
                    
                    
                    
                    
                
            
        
    
    
        
            
        
    
    
    
  3. 编写接口

    public interface UserMapper {
        public List  getUserList();
    }
    
  4. 编写Mapper.xml

    
    
    
    
    
    
        select * from mybatis.user
    
    
    
  5. 测试

import com.kuang.mapper.UserMapper;
import com.kuang.pojo.user;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

public class Mytest {
    @Test
    public void test01() throws IOException {
        String resources="mybatis-config.xml";
        InputStream in = Resources.getResourceAsStream(resources);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
        SqlSession sqlSession = sqlSessionFactory.openSession();

        UserMapper mapper = sqlSession.getMapper(UserMapper.class);
        List userList = mapper.getUserList();
        for (user user : userList) {
            System.out.println(user);
        }

    }
}

注意!!

在编写完pom.xml后一定要刷新,不然配置可能不生效!!!!

14.3、Mybatis-Spring
  1. 编写数据源配置
  2. sqlSessionFactory
  3. sqlSessionTemplate
  4. 需要给接口加实现类
  5. 将自己写的实现类,注入到spring中
  6. 测试使用即可
15、声明式事务 1、回顾事务
  • 把一组业务当做一个业务来做,要么都成功,要么都失败!
  • 事务在项目中十分重要,涉及到数据一致性问题,不能马虎!

事务ACID原则:

  • 原子性

  • 一致性

  • 隔离性

    • 多个业务可能操作同一个资源,防止数据损坏
  • 持久性

    • 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!

2.spring中的事务

  • 声明式事务:AOP,面向切面编程

    
        
            
        
    
    
    
        
    
            
                
                
                
            
        
    
    
        
            
            
        
    
  • 编程式事务:需要修改原来代码,进行事务的管理

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

tion;
import java.io.InputStream;
import java.util.List;

public class Mytest {
@Test
public void test01() throws IOException {
String resources=“mybatis-config.xml”;
InputStream in = Resources.getResourceAsStream(resources);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();

    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    List userList = mapper.getUserList();
    for (user user : userList) {
        System.out.println(user);
    }

}

}





>注意!!
>
>在编写完pom.xml后一定要刷新,不然配置可能不生效!!!!





### 14.3、Mybatis-Spring

1. 编写数据源配置
2. sqlSessionFactory
3. sqlSessionTemplate
4. 需要给接口加实现类
5. 将自己写的实现类,注入到spring中
6. 测试使用即可





## 15、声明式事务

### 1、回顾事务

- 把一组业务当做一个业务来做,要么都成功,要么都失败!
- 事务在项目中十分重要,涉及到数据一致性问题,不能马虎!

**事务ACID原则:**

- 原子性
- 一致性
- 隔离性
  - 多个业务可能操作同一个资源,防止数据损坏

- 持久性
  - 事务一旦提交,无论系统发生什么问题,结果都不会再被影响,被持久化的写到存储器中!



2.spring中的事务

- 声明式事务:AOP,面向切面编程

  ```xml
  
      
          
      
  
  
  
      
  
          
              
              
              
          
      
  
  
      
          
          
      
  • 编程式事务:需要修改原来代码,进行事务的管理

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

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/858090.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号