Spring全面详解(学习总结),Spring框架全面详解与学习总结

马肤

温馨提示:这篇文章已超过468天没有更新,请注意相关的内容是否还可用!

本文总结了Spring框架的全面详解和学习经验。介绍了Spring的核心特性,包括依赖注入、面向切面编程、数据访问等。文章还涵盖了Spring Boot和Spring Cloud等扩展组件的使用和配置方法。通过本文的学习,读者可以更好地理解Spring框架的架构和原理,掌握Spring在实际项目中的应用技巧,提高开发效率和代码质量。

  • Spring FrameWork
  • 一、 前言
  • 二、IOC(控制反转)
    • 2.1 对于IOC的理解
    • 2.2如何使用IOC
    • 2.3配置文件的解读
    • 2.4IOC容器创建bean的两种方式
    • 2.5从IOC容器中取bean
    • 2.6bean的属性如果包含特殊字符
    • 三、DI(依赖注入)
    • 四、Spring中的bean
    • 五、Spring中的继承
    • 六、Spring的依赖
    • 七、Spring读取外部资源
    • 八、Spring的p命名空间
    • 九、Spring工厂方法
      • 9.1静态工厂方法
      • 9.2实例工厂方法
      • 十、Spring IOC 自动装配 autowire
        • 10.1自动装配
        • 10.2 Spring IOC基于注解的开发
        • 10.3实际开发中的使用
        • 十一、Spring AOP

          📃个人主页: 不断前进的皮卡丘

          🌞博客描述: 梦想也许遥不可及,但重要的是追梦的过程,用博客记录自己的成长,记录自己一步一步向上攀登的印记

          🔥网站推荐:千里之行,始于足下。每天坚持刷题,巩固所学知识,也为将来找工作,面试做好准备----- 刷题神器

          文章是看楠哥的视频写的笔记

          这篇博客内容把Spring的基本知识点都讲到了,篇幅比较长,大家可以用于复习,也可以在学习相关知识点的时候,来看看对应内容。对于一些难点,IOC,AOP等,我通过流程图,代码,文字结合来进行讲解,可以更好的理解

          Spring FrameWork

          一、 前言

          • Spring是当前Java开发的行业标准,第一框架
          • Spring FrameWork已经从最初取代EJB的框架逐步发展成一套完整的生态,最新的版本是5.x
          • Spring架构体系图

            Spring全面详解(学习总结),Spring框架全面详解与学习总结 第1张

          • Spring两大核心机制:
            • IOC:工厂模式
            • AOP:代理模式

              二、IOC(控制反转)

              2.1 对于IOC的理解

              传统开发中,需要调用对象的时候,需要调用者手动来创建被调用者的实例,即对象是由调用者new出来的

              但是在Spring框架中,创建对象的工作不再由调用者来完成,而是交给IOC容器来创建,再推送给调用者,整个流程完成反转,所以是控制反转

              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第2张

              就比如说假设买东西,以前我们需要自己去超市买东西,但是现在我们可以不用自己去超市,我们只要把购物袋放在家门口,IOC就会自己去把我们想要的东西买回来,然后放在袋子里面,我们打开袋子拿起来用就可以了

              IOC的特点是解耦合。

              比如说A需要用到B,传统的开发,我们要直接创建B的实例,但是在Spring中,IOC这个容器会创建B的实例,然后把这个B注入到A

              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第3张

              2.2如何使用IOC

              • 创建maven工程,在pom.xml中导入相关依赖
                
                    4.0.0
                    org.example
                    springioc
                    1.0-SNAPSHOT
                    
                        8
                        8
                    
                    
                        
                            org.springframework
                            spring-context
                            5.3.18
                        
                    
                
                
                • 创建实体类Student
                  public class Student {
                      private long id;
                      private String name;
                      private int age;
                      public long getId() {
                          return id;
                      }
                      public void setId(long id) {
                          this.id = id;
                      }
                      public String getName() {
                          return name;
                      }
                      public void setName(String name) {
                          this.name = name;
                      }
                      public int getAge() {
                          return age;
                      }
                      public void setAge(int age) {
                          this.age = age;
                      }
                      @Override
                      public String toString() {
                          return "Student{" +
                                  "id=" + id +
                                  ", name='" + name + '\'' +
                                  ", age=" + age +
                                  '}';
                      }
                  }
                  
                  • 在resources路径下创建applicationContext.xml配置文件
                    
                        
                    
                    
                    • 传统的开发方式:手动new Student
                              Student stu =new Student();
                              stu .setAge(25);
                              stu.setId(1001);
                              stu.setName("张三");
                              System.out.println(stu);
                      
                      • IOC容器通过读取配置文件,加载配置bean标签来创建对象
                      • 就像买菜一样,我们不需要自己亲自买,但是要写一张单子,告诉说要买什么,程序也是类似的,我们要告诉Spring框架要创建哪些对象,怎样创建对象
                      • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第4张
                      • 调用API,从IOC获取对象
                        //读取配置文件
                                ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
                                Student stu = applicationContext.getBean("stu", Student.class);
                                System.out.println(stu);
                        

                        Spring全面详解(学习总结),Spring框架全面详解与学习总结 第5张

                        2.3配置文件的解读

                        • 通过配置bean标签来完成对象的管理
                        • id:对象名
                        • class:对象的模板类(所有交给IOC容器来管理的类必须要有无参构造函数,因为Spring底层是通过反射机制来创建对象,调用的是无参构造)
                        • 对象的成员变量通过property标签完成赋值
                          • name:成员变量名
                          • value:成员变量值(基本数据类型,String可以直接赋值,如果是其他引用类型不可以通过value赋值)
                          • ref:把IOC中的另一个bean赋给当前成员变量(DI)
                          • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第6张

                            2.4IOC容器创建bean的两种方式

                            • 无参构造函数(需要提供对应的set方法)

                            • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第7张

                            • 有参构造函数

                                
                                        
                                      
                                  
                              
                                
                                        
                                      
                                  
                              

                              2.5从IOC容器中取bean

                              • 通过id取值
                                 Student stu = (Student)applicationContext.getBean("stu");
                                
                                • 通过类型取值
                                   Student stu = applicationContext.getBean(  Student.class);
                                  
                                  • 当IOC容器中存在两个以上Student Bean的时候就会抛出异常,因为此时没有唯一的bean

                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第8张

                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第9张

                                    2.6bean的属性如果包含特殊字符

                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第10张

                                    三、DI(依赖注入)

                                    • DI:指bean之间的依赖注入,设置对象之间的级联关系
                                    • Classes
                                      public class Classes {
                                          private Integer id;
                                          private String name;
                                          还有对应的get,set方法
                                      }
                                      
                                      • Student
                                        public class Student {
                                            private long id;
                                            private String name;
                                            private int age;
                                            private Classes classes;
                                            public Student(){
                                                System.out.println("使用无参构造创建对象");
                                            }
                                            public Student(long id,String name){
                                                this.id = id;
                                                this.name = name;
                                            }  
                                            public Classes getClasses() {
                                                return classes;
                                            }
                                            public void setClasses(Classes classes) {
                                                this.classes = classes;
                                            }
                                            public long getId() {
                                                return id;
                                            }
                                            public void setId(long id) {
                                                this.id = id;
                                            }
                                            public String getName() {
                                                return name;
                                            }
                                            public void setName(String name) {
                                                this.name = name;
                                            }
                                            public int getAge() {
                                                return age;
                                            }
                                            public void setAge(int age) {
                                                this.age = age;
                                            }
                                            @Override
                                            public String toString() {
                                                return "Student{" +
                                                        "id=" + id +
                                                        ", name='" + name + '\'' +
                                                        ", age=" + age +
                                                        ", classes=" + classes +
                                                        '}';
                                            }
                                        }
                                        

                                        applicationContext-di.xml

                                        
                                            
                                                
                                                
                                            
                                            
                                                
                                                
                                                
                                                
                                            
                                        
                                        

                                        Spring全面详解(学习总结),Spring框架全面详解与学习总结 第11张

                                        bean之间的级联需要使用ref属性,而不能用value属性,否则会抛出类型转换异常

                                        Spring全面详解(学习总结),Spring框架全面详解与学习总结 第12张

                                        Spring全面详解(学习总结),Spring框架全面详解与学习总结 第13张

                                        
                                            
                                                
                                                
                                                
                                                    
                                                        
                                                        
                                                    
                                                
                                            
                                            
                                                
                                                
                                                
                                                
                                            
                                            
                                                
                                                
                                                
                                                
                                            
                                        
                                        

                                        Spring全面详解(学习总结),Spring框架全面详解与学习总结 第14张

                                        如果把学生装到班级里面,又把班级装到学生里面,就导致无限递归循环装配,最终栈溢出

                                        四、Spring中的bean

                                        bean是根据scope来生成的,表示bean的作用域,scope有4种类型

                                        • singleton,单例,表示通过Spring容器获取的对象是唯一的,是默认值

                                          • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第15张

                                          • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第16张

                                          • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第17张

                                          • prototype,原型,表示通过Spring容器获取的对象是不同的

                                            • 配置文件
                                                      
                                                      
                                                  
                                              

                                              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第18张

                                              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第19张

                                              • request,请求,表示在异常HTTP请求内有效
                                              • session,会话,表示在一个用户会话内有效

                                                request和session一般用于web项目

                                                singleton模式下,只要加载IOC容器,不管是否从IOC种取出bean,配置文件中的bean都会被创建,而且只会创建一个对象

                                                prototype模式下,如果不从IOC中取出bean,则不创建对象,取一次bean,就会创建一个对象

                                                五、Spring中的继承

                                                Spring中的继承不同于Java中的继承

                                                Java中的继承是针对于类的

                                                Spring中的继承是针对于对象(bean)

                                                
                                                    
                                                        
                                                        
                                                    
                                                    
                                                
                                                

                                                Spring全面详解(学习总结),Spring框架全面详解与学习总结 第20张

                                                • 通过设置bean标签的parent属性建立继承关系,同时子bean可以覆盖父bean的属性值
                                                • Spring的继承是针对对象的,所以子bean和父bean并不需要同一个数据类型,只要其成员变量列表一致即可

                                                  六、Spring的依赖

                                                  • 用来设置两个bean的创建顺序
                                                  • IOC容器默认情况下是通过applicationContext.xml中bean的配置顺序来决定创建顺序的,配置在前面的bean会先被创建
                                                  • 在不更改applicationContext.xml配置顺序的前提下,通过设置bean之间的依赖关系来调整bean的创建顺序
                                                  • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第21张

                                                    七、Spring读取外部资源

                                                    • 在实际开发中,数据库的配置会一般会单独保存到后缀为properties的文件,方便维护和修改
                                                    • 如果用Spring来加载数据源,就需要在applicationContext.xml中读取properties中的数据,这就是读取外部资源

                                                      jdbc.properties

                                                      user=root
                                                      password=root
                                                      url=jdbc:mysql://localhost:3306/spring
                                                      driverName=com.mysql.cj.jdbc.Driver
                                                      

                                                      spring-properties.xml

                                                      
                                                          
                                                          
                                                          
                                                              
                                                              
                                                              
                                                              
                                                          
                                                      
                                                      

                                                      Spring全面详解(学习总结),Spring框架全面详解与学习总结 第22张

                                                      Spring全面详解(学习总结),Spring框架全面详解与学习总结 第23张

                                                      八、Spring的p命名空间

                                                      • 用来简化xml配置
                                                      • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第24张
                                                        
                                                            
                                                            
                                                        
                                                        

                                                        九、Spring工厂方法

                                                        IOC通过工厂模式创建bean有两种方式:

                                                        • 静态工厂方法
                                                        • 实例工厂方法
                                                        • 静态工厂类不需要实例化,实例工厂类需要实例化

                                                          9.1静态工厂方法

                                                          1. 创建Car类
                                                          public class Car {
                                                              private Integer num;
                                                              private String brand;
                                                              public Car() {
                                                              }
                                                              public Car(Integer num, String brand) {
                                                                  this.num = num;
                                                                  this.brand = brand;
                                                              }
                                                              public Integer getNum() {
                                                                  return num;
                                                              }
                                                              public void setNum(Integer num) {
                                                                  this.num = num;
                                                              }
                                                              public String getBrand() {
                                                                  return brand;
                                                              }
                                                              public void setBrand(String brand) {
                                                                  this.brand = brand;
                                                              }
                                                              @Override
                                                              public String toString() {
                                                                  return "Car{" +
                                                                          "num=" + num +
                                                                          ", brand='" + brand + '\'' +
                                                                          '}';
                                                              }
                                                          }
                                                          
                                                          1. 创建静态工厂类,静态工厂方法
                                                          public class StaticCarFactory {
                                                              private static Map carMap;
                                                              static {
                                                                  carMap = new HashMap();
                                                                  carMap.put(1, new Car(1, "奥迪"));
                                                                  carMap.put(2, new Car(2,"奥拓"));
                                                              }
                                                              /**
                                                               * 写一个方法,从map集合取数据
                                                               */
                                                              public static Car getCar(Integer num ){
                                                                  return carMap.get(num);
                                                              }
                                                          }
                                                          
                                                          1. spring-factory.xml
                                                          
                                                              
                                                                  
                                                              
                                                          
                                                          
                                                          • factory-method 指向静态方法
                                                          • constructor-arg的value属性是调用静态方法传入的参数

                                                            9.2实例工厂方法

                                                            1. 创建实例工厂类,工厂方法
                                                            public class InstanceCarFactory {
                                                                private Map carMap;
                                                                public InstanceCarFactory() {
                                                                    carMap = new HashMap();
                                                                    carMap.put(1, new Car(1, "奥迪"));
                                                                    carMap.put(2, new Car(2, "奥拓"));
                                                                }
                                                                public Car getCar(Integer num){
                                                                    return carMap.get(num);
                                                                }
                                                            }
                                                            
                                                            1. spring.xml
                                                                
                                                            
                                                                
                                                                    
                                                                
                                                            

                                                            区别:

                                                            Spring全面详解(学习总结),Spring框架全面详解与学习总结 第25张

                                                            • 静态工厂方法创建Car对象,不需要实例化工厂对象,因为静态工厂的静态方法,不需要创建对象就可以调用了
                                                            • 实例工厂方法创建Car对象,需要实例化工厂对象,因为getCar方法是非静态的,就必须通过实例化对象才能调用,所以 必须创建工厂对象,spring.xml需要配置两个bean,一个是工厂bean,一个是Car Bean
                                                            • spring.xml中 class+factory-method的形式是直接调用类中的工厂方法
                                                            • spring.xml中factory-bean+factory-method的形式是调用工厂bean中的工厂方法,就必须先创建工厂bean

                                                              十、Spring IOC 自动装配 autowire

                                                              10.1自动装配

                                                              • 自动装载是Spring提供的一种更加简便的方式来完成DI,不需要手动配置property,IOC 容器会自动选择bean来完成注入
                                                              • 自动装载有两种方式:
                                                                • byName:通过属性名完成自动装载
                                                                • byType:通过属性对应的数据类型完成自动装载

                                                                  byName的操作如下:

                                                                  1. 创建Person实体类
                                                                  public class Person {
                                                                      private Integer id;
                                                                      private String name;
                                                                      private Car car;
                                                                      public Integer getId() {
                                                                          return id;
                                                                      }
                                                                      public void setId(Integer id) {
                                                                          this.id = id;
                                                                      }
                                                                      public String getName() {
                                                                          return name;
                                                                      }
                                                                      public void setName(String name) {
                                                                          this.name = name;
                                                                      }
                                                                      public Car getCar() {
                                                                          return car;
                                                                      }
                                                                      public void setCar(Car car) {
                                                                          this.car = car;
                                                                      }
                                                                      @Override
                                                                      public String toString() {
                                                                          return "Person{" +
                                                                                  "id=" + id +
                                                                                  ", name='" + name + '\'' +
                                                                                  ", car=" + car +
                                                                                  '}';
                                                                      }
                                                                  }
                                                                  
                                                                  1. 在spring.xml中配置Car和Person对应的bean,并且通过自动装载完成依赖注入
                                                                  
                                                                      
                                                                          
                                                                          
                                                                      
                                                                      
                                                                      
                                                                          
                                                                          
                                                                      
                                                                  
                                                                  

                                                                  Spring全面详解(学习总结),Spring框架全面详解与学习总结 第26张

                                                                  注:如果bean的id有多个一致的,会报错,如Bean name 'car' is already used in this element

                                                                  byType的操作如下:

                                                                  
                                                                      
                                                                          
                                                                          
                                                                      
                                                                      
                                                                      
                                                                          
                                                                          
                                                                      
                                                                  
                                                                  

                                                                  Spring全面详解(学习总结),Spring框架全面详解与学习总结 第27张

                                                                  使用byType进行自动装配的时候,必须保证IOC中有且只有一个符合,如果有多个符合,则报下面的异常:

                                                                  Spring全面详解(学习总结),Spring框架全面详解与学习总结 第28张

                                                                  10.2 Spring IOC基于注解的开发

                                                                  Spring IOC的作用是帮助开发者创建项目中所需要的bean,同时完成bean之间的依赖注入关系,DI

                                                                  实现该功能有两种方式:

                                                                  • 基于XML配置
                                                                  • 基于注解

                                                                    基于注解有两步操作,缺一不可:

                                                                    1. 配置自动扫包
                                                                    2. 添加注解
                                                                    
                                                                    
                                                                        
                                                                    
                                                                    
                                                                    
                                                                    @Component(value="repository")
                                                                    public class Repository {
                                                                        private DataSource dataSource;
                                                                        public DataSource getDataSource() {
                                                                            return dataSource;
                                                                        }
                                                                        public void setDataSource(DataSource dataSource) {
                                                                            this.dataSource = dataSource;
                                                                        }
                                                                        @Override
                                                                        public String toString() {
                                                                            return "Repository{" +
                                                                                    "dataSource=" + dataSource +
                                                                                    '}';
                                                                        }
                                                                    }
                                                                    

                                                                    DI

                                                                    注解默认的beanid是类名以小写开头,我们可以通过value来设置

                                                                    如果我们想要把datasource也注入进来需要怎么做呢?

                                                                    首先我们要把DataSource先扫进来

                                                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第29张

                                                                    @Component
                                                                    public class Repository {
                                                                        @Autowired
                                                                        private DataSource dataSource;
                                                                        public DataSource getDataSource() {
                                                                            return dataSource;
                                                                        }
                                                                        public void setDataSource(DataSource dataSource) {
                                                                            this.dataSource = dataSource;
                                                                        }
                                                                        @Override
                                                                        public String toString() {
                                                                            return "Repository{" +
                                                                                    "dataSource=" + dataSource +
                                                                                    '}';
                                                                        }
                                                                    }
                                                                    

                                                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第30张

                                                                    Spring全面详解(学习总结),Spring框架全面详解与学习总结 第31张

                                                                    • @Autowired默认是通过byType进行装配,如果要改为byName,需要配合@Qualifier注解来完成
                                                                      @Component
                                                                      public class Repository {
                                                                          @Autowired
                                                                          @Qualifier(value = "datasource")
                                                                          private DataSource dataSource;
                                                                          public DataSource getDataSource() {
                                                                              return dataSource;
                                                                          }
                                                                          public void setDataSource(DataSource dataSource) {
                                                                              this.dataSource = dataSource;
                                                                          }
                                                                          @Override
                                                                          public String toString() {
                                                                              return "Repository{" +
                                                                                      "dataSource=" + dataSource +
                                                                                      '}';
                                                                          }
                                                                      }
                                                                      

                                                                      这表明把IOC中id为datasource的bean注入到repository中

                                                                      实体类中普通的成员变量(String,包装类等),可以通过@Value注解来赋值

                                                                      @Component
                                                                      public class DataSource {
                                                                          @Value("root")
                                                                          private String username;
                                                                          @Value("123456")
                                                                          private String password;
                                                                          @Value("jdbc:mysql://localhost:3306/spring")
                                                                          private String url;
                                                                          @Value("com.mysql.cj.jdbc.Driver")
                                                                          private String driveName;
                                                                       }
                                                                      

                                                                      10.3实际开发中的使用

                                                                      实际开发中我们会把程序分成三层:

                                                                      • Controller
                                                                      • Service
                                                                      • Repository(DAO)
                                                                      • 关系Controller—>Service---->Repository
                                                                      • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第32张

                                                                        @Component注解是把标注的类加载到IOC容器中,实际开发中可以根据业务需求分别使用@Controller,@Service,@Repository注解来标注控制层类,业务层类,持久层类

                                                                        十一、Spring AOP

                                                                        • AOP (Aspect Oriented Programming) 面向切面编程
                                                                        • OOP (Object Oriented Programming) 面向对象编程,用对象化的思想来完成程序
                                                                        • AOP是对OOP的一个补充,是在另外一个维度上抽象出对象
                                                                        • 具体指程序运行时动态地把非业务代码切入到业务代码中,从而实现程序的解耦合,把非业务代码抽象成一个对象,对对象编程就是面向切面编程
                                                                        • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第33张
                                                                        • 上面这种形式的代码维护性很差,代码复用性差
                                                                        • Spring全面详解(学习总结),Spring框架全面详解与学习总结 第34张

                                                                          AOP的优点:

                                                                        • 可以降低模块之间的耦合性
                                                                        • 提供代码的复用性
                                                                        • 提高代码的维护性
                                                                        • 集中管理非业务代码,便于维护
                                                                        • 业务代码不受非业务代码影响,逻辑更加清晰

                                                                          通过一个例子来理解AOP。

                                                                          1. 创建一个计算器接口Cal
                                                                          public interface Cal {
                                                                           public int add(int num1,int num2);
                                                                           public int sub(int num1,int num2);
                                                                           public int mul(int num1,int num2);
                                                                           public int div(int num1,int num2);
                                                                          }
                                                                          
                                                                          1. 创建接口的实现类
                                                                          public class CalImpl implements Cal {
                                                                              @Override
                                                                              public int add(int num1, int num2) {
                                                                                  int res = num1 + num2;
                                                                                  return res;
                                                                              }
                                                                              @Override
                                                                              public int sub(int num1, int num2) {
                                                                                  int res = num1 - num2;
                                                                                  return res;
                                                                              }
                                                                              @Override
                                                                              public int mul(int num1, int num2) {
                                                                                  int res = num1 * num2;
                                                                                  return res;
                                                                              }
                                                                              @Override
                                                                              public int div(int num1, int num2) {
                                                                                 int res=num1/num2;
                                                                                 return res;
                                                                              }
                                                                          }
                                                                          

                                                                          日志打印

                                                                          • 在每个方法开始位置输出参数信息
                                                                          • 在每个方法结束位置输出结果信息

                                                                            对于计算器来说,加减乘除就是业务代码,日志打印就是非业务代码

                                                                            AOP如何实现? 使用动态代理的方式来实现

                                                                            代理首先要具备CalImpl的所有功能(实现同一个接口),并且在这个基础上,扩展出打印日志的功能

                                                                            1. 删除CalImpl方法中国所有打印日志的代码,只保留业务代码
                                                                            2. 创建MyInvocationHandler类(不是动态代理类),实现InvocationHandler接口,生成动态代理类 。动态代理类需要动态生成,需要获取到委托类的接口信息,根据这些接口信息动态生成一个代理类,然后再由ClassLoader用来把动态生成的类加载到JVM

                                                                              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第35张

                                                                              ClassLoader用来把动态生成的类加载到JVM中

                                                                              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第36张

                                                                              代理类需要有和委托类一样的功能,所以委托类和代理类需要实现同样的接口,因此,我们要获取到委托类的接口信息,根据这个接口信息就可以生成一个类,再通过ClassLoader加载到内存里面

                                                                            public class MyInvocationHandler implements InvocationHandler {
                                                                                //委托对象
                                                                                private Object object = null;
                                                                                //返回代理对象
                                                                                public Object bind(Object object) {
                                                                                    this.object = object;
                                                                                    return Proxy.newProxyInstance(object.getClass().getClassLoader(),
                                                                                            object.getClass().getInterfaces(),this);
                                                                                }
                                                                                @Override
                                                                                public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                                                                                    //实现业务代码和非业务代码的解耦合
                                                                                    System.out.println(method.getName()+"方法的参数是:"+ Arrays.toString(args));
                                                                                    Object res = method.invoke(this.object, args);
                                                                                    System.out.println(method.getName()+"方法的结果是:"+res);
                                                                                    return res;
                                                                                }
                                                                            }
                                                                            

                                                                            Spring全面详解(学习总结),Spring框架全面详解与学习总结 第37张

                                                                            上述代码通过动态代理机制实现了业务代码和非业务代码的解耦合,这是Spring AOP的底层实现机制,真正使用 Spring AOP进行开发的时候,不需要这么复杂

                                                                            Spring AOP的开发步骤

                                                                            1. 创建切面类 Loggerspect
                                                                            @Component
                                                                            @Aspect
                                                                            public class LoggerAspect {
                                                                                @Before("execution(public int com.zyh.aop.impl.CalImpl.*(..))")
                                                                                public void before(JoinPoint joinPoint) {
                                                                                    String name = joinPoint.getSignature().getName();
                                                                                    Object[] args = joinPoint.getArgs();
                                                                                    System.out.println(name + "方法的参数是:" + Arrays.toString(args));
                                                                                }
                                                                                @After("execution(* com.zyh.aop.impl.CalImpl.*(..))")
                                                                                public void after(JoinPoint joinPoint){
                                                                                    String name = joinPoint.getSignature().getName();
                                                                                    System.out.println(name+"方法执行完毕");
                                                                                }
                                                                                @AfterReturning(value = "execution(* com.zyh.aop.impl.CalImpl.*(..))",returning = "rs")
                                                                                public void afterReturning(JoinPoint joinPoint,Object rs){
                                                                                    String name = joinPoint.getSignature().getName();
                                                                                    System.out.println(name+"方法执行的结果是:"+rs);
                                                                                }
                                                                            @AfterThrowing(value = "execution(* com.zyh.aop.impl.CalImpl.*(..))",throwing = "ex")
                                                                                public void afterThrowing(JoinPoint joinPoint,Exception ex){
                                                                                String name = joinPoint.getSignature().getName();
                                                                                System.out.println(name+"方法抛出异常"+ex);
                                                                            }
                                                                            }
                                                                            
                                                                            • @Component,把切面类加载到IOC容器中
                                                                            • @Aspect,表示该类是一个切面类
                                                                            • @Before,表示方法的执行时机是在业务方法之前,execution表达式表示切入点是CalImpl中的所有方法
                                                                            • @After,表示方法的执行时机是在业务方法结束以后,execution表达式表示切入点是CalImpl类中的方法
                                                                            • @AfterReturning,表示方法的执行时机是在业务方法返回结果后,execution表达式表示切入点是CalImpl类中的方法,returning是把业务方法的返回值和切面类方法的形参进行绑定
                                                                            • @AfterThrowing,表示方法的执行时机是在业务方法抛出异常后,execution表达式表示切入点是CalImpl类中的方法,throwing是把业务方法的异常和切面类方法的形参进行绑定

                                                                              Spring全面详解(学习总结),Spring框架全面详解与学习总结 第38张

                                                                              1. 委托类也需要添加@Component
                                                                              @Component
                                                                              public class CalcImpl implements Calc{
                                                                                  @Override
                                                                                  public int add(int a, int b) {
                                                                                      int result=a+b;
                                                                                      return result;
                                                                                  }
                                                                                  @Override
                                                                                  public int sub(int a, int b) {
                                                                                     int result=a-b;
                                                                                     return result;
                                                                                  }
                                                                                  @Override
                                                                                  public int mul(int a, int b) {
                                                                                      int result= a*b;
                                                                                      return result;
                                                                                  }
                                                                                  @Override
                                                                                  public int div(int a, int b) {
                                                                                      int result= a/b;
                                                                                      return result;
                                                                                  }
                                                                              }
                                                                              

                                                                              3.spring-aop.xml

                                                                              
                                                                                  
                                                                                  
                                                                              
                                                                                 
                                                                              
                                                                              
                                                                              • aspectj-autoproxy ,Spring IOC容器会结合切面对象和委托对象自动生成动态代理对象,AOP底层就是通过动态代理机制来实现的

                                                                                4.测试

                                                                                Spring全面详解(学习总结),Spring框架全面详解与学习总结 第39张

                                                                                AOP的概念

                                                                                • 切面对象:根据切面抽象出来的对象,CalImpl所有方法中需要加入日志的部分LoggerAspect
                                                                                • 通知:切面对象具体执行的代码,即非业务代码,LoggerAspect对象打印日志的代码
                                                                                • 目标:被横切的对象,即CalImpl,把通知加入其中
                                                                                • 代理:切面对象,通知,目标混合后的结果,即我们通过JDK动态代理机制创建的对象
                                                                                • 连接点:需要被横切的位置,即通知要插入业务代码的具体位置

0
收藏0
文章版权声明:除非注明,否则均为VPS857原创文章,转载或复制请以超链接形式并注明出处。

相关阅读

  • 【研发日记】Matlab/Simulink自动生成代码(二)——五种选择结构实现方法,Matlab/Simulink自动生成代码的五种选择结构实现方法(二),Matlab/Simulink自动生成代码的五种选择结构实现方法详解(二)
  • 超级好用的C++实用库之跨平台实用方法,跨平台实用方法的C++实用库超好用指南,C++跨平台实用库使用指南,超好用实用方法集合,C++跨平台实用库超好用指南,方法与技巧集合
  • 【动态规划】斐波那契数列模型(C++),斐波那契数列模型(C++实现与动态规划解析),斐波那契数列模型解析与C++实现(动态规划)
  • 【C++】,string类底层的模拟实现,C++中string类的模拟底层实现探究
  • uniapp 小程序实现微信授权登录(前端和后端),Uniapp小程序实现微信授权登录全流程(前端后端全攻略),Uniapp小程序微信授权登录全流程攻略,前端后端全指南
  • Vue脚手架的安装(保姆级教程),Vue脚手架保姆级安装教程,Vue脚手架保姆级安装指南,Vue脚手架保姆级安装指南,从零开始教你如何安装Vue脚手架
  • 如何在树莓派 Raspberry Pi中本地部署一个web站点并实现无公网IP远程访问,树莓派上本地部署Web站点及无公网IP远程访问指南,树莓派部署Web站点及无公网IP远程访问指南,本地部署与远程访问实践,树莓派部署Web站点及无公网IP远程访问实践指南,树莓派部署Web站点及无公网IP远程访问实践指南,本地部署与远程访问详解,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南,树莓派部署Web站点及无公网IP远程访问实践详解,本地部署与远程访问指南。
  • vue2技术栈实现AI问答机器人功能(流式与非流式两种接口方法),Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法探究,Vue2技术栈实现AI问答机器人功能,流式与非流式接口方法详解
  • 发表评论

    快捷回复:表情:
    评论列表 (暂无评论,0人围观)

    还没有评论,来说两句吧...

    目录[+]

    取消
    微信二维码
    微信二维码
    支付宝二维码