[Spring]基础

JavaBean

  • JavaBean就是有一定规范的Java实体类,跟普通的类差不多。
  • 不通过的hi类内部提供了一些公共方法以便外界对该对象内部属性进行操作,比如set、get操作,实际上,就是我们之前一直在用的:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    public class User{
    private String name;
    private int age;
    public String getName(){
    return name;
    }
    public String getAge(){
    return age;
    }
    public void setName(String name){
    this.name = name;
    }
    public void setAge(int age){
    this.age = age;
    }
    }
  • 它的所有属性都是private,所有的属性都可以通过get/set方法进行访问,同时还需要有一个无参构造(默认就有)

JavaBeande的生命周期

  • 1.创建:
    • 当程序创建Java Bean的实例时,Java虚拟机将分配内存来存储对象。
    • 并可以对JavaBean的属性进行初始化。
  • 2.初始化:
    • 在JavaBean实例化之后,程序可以对JavaBean的属性进行设置。
    • 通常,这些属性可以通过公共setter方法设置。
  • 3.活动:
    • JavaBean处于活动状态时,可以执行一些操作。
    • 例如响应事件、更新属性等。
  • 4.销毁:
    • 当JavaBean不再需要时,Java虚拟机会释放对象所占用的内存。
    • 此时调用JavaBean的析构函数,可以在该函数中释放与JavaBean相关的资源。
  • JavaBean的生命周期通常由JVM自动管理,程序员不需要显式的控制JavaBean的生命周期。
  • 但是,可以通过编写JavaBean的构造函数和析构函数等方法来实现自定义生命周期管理。
  • 也可以通过容器框架来更方便的管理JavaBean的生命周期。

Spring中的Bean周期

  • 1.实例化:通过反射或者工厂方式创建Bean的实例。
  • 2.配置Bean属性:创建实例后,容器将使用setter方法或依赖注入的方式设置bean的属性。
  • 3.BeanPostProcessor前置处理器:在bean实例化之后,容器会调用所有实现了BeanPostProcessor接口的类的postProcessBeforeInitialization()方法。
  • 4.初始化Bean:在所有的属性都被设置了之后,容器会调用bean的初始化方法。初始化方法可以时自定义的方法,也可以时通过InitializingBean接口调用afterPropertiesSet()方法。
  • 5.BeanPostProcessor后置处理器:在bean初始化之后,容器会调用所有实现了BeanPostProcessor接口类的postProcessAfterInitialization()方法。
  • 6.使用Bean:现在Bean可以被应用程序使用了。
  • 7.销毁Bean:当应用程序关闭时,容器会销毁Bean。销毁方法可以是自定义的方法,也可以时通过DisposableBean接口来调用destory()方法。

IOC容器

  • 控制反转(IOC)是一种设计模式。
  • 它的目的是降低代码之间的耦合度,提高带啊的可重用行、可扩展性和可维护性。
  • 把复杂系统分解成相互合作的对象,这些对象类通过封装后,内部实现对外部是透明的,从而降低了解决问题的复杂读,可以灵活地重用和扩展。
  • Service的实现类,不再由我们实现,而是让程序自己决定,所有的实现类对象,全部交友程序来管理,所有对象之间的关系,也由程序来动态决定,这样就引入了IOC理论。

  • 将对象交给Ioc容器进行管理。

  • 当我们需要一个接口的实现时,由它根据配置文件决定到底给我们哪一个实现类,这样我们就可以不用再关系我们需要哪一个实现类了

使用IOC容器

将JavaBean交给IoC容器管理

1
<bean name="student" class="com.test.bean.Student"/>

其中name属性(也可以是id属性),全局唯一,不可出现重复的名称,我们发现,之前其实就是通过Bean的名称来向IoC容器索要对应的对象,也可以通过其他方式获取。

  • 现在在主方法中连续获取两个对象:
    1
    2
    3
    4
    5
    6
    7
    8
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("test.xml");
    Student student = (Student) context.getBean("student");
    Student student2 = (Student) context.getBean("student");
    System.out.println(student);
    System.out.println(student2);
    out:
    com.test.bean.Student@367ffa75
    com.test.bean.Student@367ffa75

  • 我们发现两次获取到的实际上是同一个对象,也就是说,默认情况下,通过IoC容器进行管理的JavaBean是单例模式的。
    • 单例模式:确保一个类只有一个实例,并提供一个全局访问点。
    • 单例模式的实现方法由很多种,常见的是饿汉模式和懒汉模式:
      • 饿汉模式:
        • 类加载时就创建实例,因此他的实例化是先安全的。
        • 饿汉模式实现比较简单,可以直接在类中定义一个私有的静态实例,并提供给一个公共的静态方法来获取该实例。
        • 由于类加载时就创建实例,所以可能会造成资源的浪费。
      • 懒汉模式:
        • 第一次使用时才创建实例,因此他的实例时延迟的。
        • 实现比较复杂,需要考虑多线程环节下的线程安全问题。
        • 常见的实现方法欧双重检查锁和静态内部类。
          -双重检查锁指在获取实例时先进行一次判断,如果实例不存在就加锁创建实例,可以避免多次加锁,提高效率。
        • 静态内部类则是利用了类的加载机制实现延迟加载。静态内部类只有被调用时才会加载,因此可以实现延迟加载并保证线程安全。
      • 都是为了保证系统中只有一个实例存在。饿汉模式适用于单线程,懒汉模式适用于多线程。
  • 无论怎么获取始终为那一个对象,那么如何进行修改呢?只需要修改其作用域即可,添加scope属性:
    1
    <bean name="student" class="com.test.bean.Student" scope="prototype"/>
  • 通过将其设定为prototype(原型模式)来使得其每次都会创建一个新的对象。

  • 单例模式时,对象在一开始就被创建。Bean会被IoC容器存储,只要容器没有被销毁,那么对象将一直存在。

  • 原型模式下,只有在获取时才会被创建。相当于直接new了一个对象,并不会被保存。

依赖注入

  • 向Bean成员属性进行赋值时,可以使用property标签来实现

AOP

  • 在运行时,动态地将代码切入到类的指定当发、指定位置的编程思想。
  • 也就是说,我么可以使用AOP来帮助我们在方法执行之前或执行之后,做一些额外的操作,实际上就是代理。

AOP的核心概念包括:

  • 1.切面(Aspet):定一个横切关注点的模块,例如日志记录、事务管理等。
  • 2.连接点(Join Point):程序执行过程中的一个点,例如方法调用或异常抛出等。
  • 3。通知(Advice):定义了在连接点执行之前、执行之后或执行过程进行拦截和处理的逻辑。
  • 4.引入(Introductio):允许在运行时为类添加新的方法或属性。
  • 5.切点(PointCut):用于定义连接点的匹配规则,例如指定拦截哪些方法或哪些类。
  • 6.织入(Weaving):将切面应用程序代码中,可以在编译时、类加载时或运行时进行。

根据通知的执行时间,AOP可以分为以下几种类型:

  • 前置通知(Before Advice):在连接点之前执行的通知,通常用于记录日志或进行安全性检查。
  • 后置通知(After Advice):在连接点之后进行的通知,通常用于清理资源或记录日志。
  • 环绕通知(Around Advice):在连接点之前和之后都执行点饿通知,通常用于事务管理或者性能监控。
  • 异常通知(After Throwing Advice):在连接点抛出异常时执行的通知,通常用于处理异常并记录日志。
  • 返回通知(After Returning Advice):在连接点正常返回结果时执行的通知,通常用于记录日志或进行缓存操作。

使用注解实现AOP

  • 首先我们需要在主类添加@EnableAspectJAutoProxy注解,开启AOP注解支持:
    1
    2
    3
    4
    5
    @EnableAspectJAutoProxy
    @ComponentScan("org.example.entity")
    @Configuration
    public class MainConfiguration {
    }
  • 类上直接添加@Component快速注册Bean:
    1
    2
    3
    4
    5
    6
    @Component
    public class Student {
    public void study(){
    System.out.println("我是学习方法!");
    }
    }
  • 需要在定义AOP增强操作的类上添加@Aspect注解和@Component将其注册为Bean即可,就像我们之前在配置文件中也要将其注册为Bean那样:
    1
    2
    3
    4
    5
    @Aspect
    @Component
    public class StudentAOP {

    }
  • 比如我们希望在Student的study方法执行之前执行我们的before方法:
    1
    2
    3
    public void before(){
    System.out.println("我是之前执行的内容!");
    }
  • 那么只需要添加@Before注解即可:
    1
    2
    3
    4
    @Before("execution(* org.example.entity.Student.study())")  //execution写法跟之前一样
    public void before(){
    System.out.println("我是之前执行的内容!");
    }