129.【Spring 注解_IOC】(四)

简介: 129.【Spring 注解_IOC】

3.使用JSR250规范 (第四种)

(1).@PostConstruct 和 @PreDestroy

@PostConstruct:在bean创建完成并且属性值赋值完成后执行初始化;

@PreDestroy:在容器销毁bean之前,通知容器进行清理工作;

1.需要被注册的组件

package com.jsxs.bean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
 * @Author Jsxs
 * @Date 2023/8/16 15:37
 * @PackageName:com.jsxs.bean
 * @ClassName: Dog
 * @Description: TODO
 * @Version 1.0
 */
public class Dog {
    public Dog() {
        System.out.println("dog constructor...");
    }
    @PostConstruct   ⭐
    public void init() {
        System.out.println("dog 初始化中...");
    }
    @PreDestroy() ⭐
    public void destroy() {
        System.out.println("dog 销毁中...");
    }
}

2.配置类: 注册需要的组件

package com.jsxs.config;
import com.jsxs.bean.Car;
import com.jsxs.bean.Car01;
import com.jsxs.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @Author Jsxs
 * @Date 2023/8/14 17:04
 * @PackageName:com.jsxs.config
 * @ClassName: MainConfigOfLifeCycle
 * @Description: TODO  Bean的生命周期
 * bean 创建 -> 初始化 -> 销毁的过程
 * 容器管理bean的生命周期; 我们可以自定义生命周期中的 初始化环节和销毁的环节。容器在bean运行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
 * 1. init-method="" destroy-method=""
 * 2. 构造(对象创建)
 * 单实列: 在容器启动的时候创建对象
 * 多实列: 在调用到组件的时候创建对象
 * @Version 1.0
 */
@Configuration
public class MainConfigOfLifeCycle {
    // 第一个参数是指定组件的别名,第二参数是指定组件的销毁方法,第三个参数是指定组件的初始方法。
    @Bean(value = "car", destroyMethod = "destroy", initMethod = "init")
    public Car car() {
        return new Car();
    }
    @Bean
    public Car01 car01() {
        return new Car01();
    }
    @Bean  ⭐
    public Dog dog(){
        return new Dog();
    }
}

3.测试

package com.jsxs.Test;
import com.jsxs.config.MainConfigOfLifeCycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @Author Jsxs
 * @Date 2023/8/14 17:16
 * @PackageName:com.jsxs.Test
 * @ClassName: IOC_LifeStyle
 * @Description: TODO
 * @Version 1.0
 */
public class IOC_LifeStyle {
    public static void main(String[] args) {
        // 1.创建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        // 2.关闭容器,当容器关闭的时候我们所有的组件也就会销毁
        applicationContext.close();
        // 1.遍历所有IOC容器中的组件
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }
}

4.BeanPostProcessor后置处理器 (第五种)

(1).BeanPostProcessor 后置处理器

后置处理器相当于在组件初始化之前做什么,初始化之后我们还做什么?

我们的Bean需要继承一个接口 BeanPostProcessor 并且完成两个方法。

在bean的初始化方法之前初始化方法之后进行一些处理工作。注意是初始化方法,和销毁方法没有一毛钱的关系。

初始化方法之前: 调用:postProcessBeforeInitialization()

初始化方法之后:调用:postProcessAfterInitialization()

即使没有自定义初始化方法,在组件创建前后,后置处理器方法也会执行。

1.注册我们的后置处理器

package com.jsxs.bean;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
 * @Author Jsxs
 * @Date 2023/8/16 15:51
 * @PackageName:com.jsxs.bean
 * @ClassName: MyBeanPostProcessor
 * @Description: TODO  我们需要实现一个 BeanPostProcessor 接口,并且完成两个方法
 * @Version 1.0
 */
@Component ⭐
public class MyBeanPostProcessor implements BeanPostProcessor {  ⭐⭐
    /**
     * @param bean     新建组件的实列
     * @param beanName 新建组件实列的名字
     * @return 返回的是组件的信息
     * @throws BeansException
     */
    @Override  ⭐⭐⭐
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "----->" + bean);
        return bean;
    }
    /**
     * @param bean     新建组件的实列
     * @param beanName 新建组件实列的名字
     * @return  返回的是组件的信息
     * @throws BeansException
     */
    @Override ⭐⭐⭐⭐
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "----->" + bean);
        return bean;
    }
}

2.配置类扫描我们的后置处理器

package com.jsxs.config;
import com.jsxs.bean.Car;
import com.jsxs.bean.Car01;
import com.jsxs.bean.Dog;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
/**
 * @Author Jsxs
 * @Date 2023/8/14 17:04
 * @PackageName:com.jsxs.config
 * @ClassName: MainConfigOfLifeCycle
 * @Description: TODO  Bean的生命周期
 * bean 创建 -> 初始化 -> 销毁的过程
 * 容器管理bean的生命周期; 我们可以自定义生命周期中的 初始化环节和销毁的环节。容器在bean运行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
 * 1. init-method="" destroy-method=""
 * 2. 构造(对象创建)
 * 单实列: 在容器启动的时候创建对象
 * 多实列: 在调用到组件的时候创建对象
 * @Version 1.0
 */
@Configuration
@ComponentScan(value = "com.jsxs")  ⭐
public class MainConfigOfLifeCycle {
    // 第一个参数是指定组件的别名,第二参数是指定组件的销毁方法,第三个参数是指定组件的初始方法。
    @Bean(value = "car", destroyMethod = "destroy", initMethod = "init")
    public Car car() {
        return new Car();
    }
    @Bean
    public Car01 car01() {
        return new Car01();
    }
    @Bean
    public Dog dog(){
        return new Dog();
    }
}

3.测试类

package com.jsxs.Test;
import com.jsxs.config.MainConfigOfLifeCycle;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @Author Jsxs
 * @Date 2023/8/14 17:16
 * @PackageName:com.jsxs.Test
 * @ClassName: IOC_LifeStyle
 * @Description: TODO
 * @Version 1.0
 */
public class IOC_LifeStyle {
    public static void main(String[] args) {
        // 1.创建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        // 2.关闭容器,当容器关闭的时候我们所有的组件也就会销毁
        applicationContext.close();
        // 1.遍历所有IOC容器中的组件
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }
}

5.Spring底层对BeanPostProcessor的使用

(1). 【案例1】在实体类中获取ioc容器

1.实体类

package com.jsxs.bean;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/**
 * @Author Jsxs
 * @Date 2023/8/16 15:37
 * @PackageName:com.jsxs.bean
 * @ClassName: Dog
 * @Description: TODO
 * @Version 1.0
 */
public class Dog implements ApplicationContextAware {  // ⭐继承这个IOC接口
    private ApplicationContext applicationContext;  // ⭐⭐
    public Dog() {
        System.out.println("dog constructor...");
    }
    @PostConstruct
    public void init() {
        System.out.println("dog 初始化中...");
    }
    @PreDestroy()
    public void destroy() {
        System.out.println("dog 销毁中...");
    }
    @Override // ⭐⭐⭐
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext=applicationContext;
    }
    // ⭐⭐⭐⭐ 自己写一个获取IOC容器的方法 (便于调用)
    public ApplicationContext getApplicationContext(){
        return applicationContext;
    }
}

2.测试

package com.jsxs.Test;
import com.jsxs.bean.Dog;
import com.jsxs.config.MainConfigOfLifeCycle;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
/**
 * @Author Jsxs
 * @Date 2023/8/14 17:16
 * @PackageName:com.jsxs.Test
 * @ClassName: IOC_LifeStyle
 * @Description: TODO
 * @Version 1.0
 */
public class IOC_LifeStyle {
    public static void main(String[] args) {
        // 1.创建IOC容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        // 2.关闭容器,当容器关闭的时候我们所有的组件也就会销毁
        applicationContext.close();
        // 1.遍历所有IOC容器中的组件
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        ConfigurableEnvironment environment1 = applicationContext.getEnvironment();
        System.out.println(environment1.getProperty("os.name"));
    // ⭐我们创建实列,并且  
        Dog dog = new Dog();
        ApplicationContext applicationContext1 = dog.getApplicationContext();
        for (String beanDefinitionName : applicationContext1.getBeanDefinitionNames()) {
            System.out.println("--->"+beanDefinitionName);
        }
    }
}

(三)、属性赋值相关的注解

/**
     * 使用@Value赋值
     *    1、基本数值
     *    2、可以些SpEL,#{}
     *    3、可以写${},取出配置文件中的值(即在运行环境变量中的值).
     *      通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,
     *      Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
     */

1.@Value

(1).普通属性赋值 和 SPEL表达式赋值

1.需要注册的组件

package com.jsxs.bean;
import org.springframework.beans.factory.annotation.Value;
/**
 * @Author Jsxs
 * @Date 2023/8/11 19:57
 * @PackageName:com.jsxs.bean
 * @ClassName: Person
 * @Description: TODO
 * @Version 1.0
 */
public class Person {
  // ⭐ 
    @Value("李明")
    private String name;
    //  ⭐⭐ spel表达式
    @Value("#{20-2}")
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.配置类

package com.jsxs.config;
import com.jsxs.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
 * @Author Jsxs
 * @Date 2023/8/17 9:05
 * @PackageName:com.jsxs.config
 * @ClassName: MainConfigOfPropertyValues
 * @Description: TODO
 * @Version 1.0
 */
@Configuration
public class MainConfigOfPropertyValues {
    @Bean
    public Person person() {
        return new Person();
    }
}

3.测试

package com.jsxs.Test;
import com.jsxs.bean.Person;
import com.jsxs.config.MainConfigOfPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @Author Jsxs
 * @Date 2023/8/17 9:07
 * @PackageName:com.jsxs.Test
 * @ClassName: IOCTest_PropertyValue
 * @Description: TODO
 * @Version 1.0
 */
public class IOCTest_PropertyValue {
    public static void main(String[] args) {
        // 1.创建IOC容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
        for (String beanDefinitionName : annotationConfigApplicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        // 2.通过组件名获取具体的组件信息
        Person person = (Person)annotationConfigApplicationContext.getBean("person");
        System.out.println(person);
    }
}

2. @PropertySource 加载外部配置文件

(1).使用配置文件的方式加载外部文件

1.beans.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
     http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
     http://www.springframework.org/schema/context
     http://www.springframework.org/schema/context/spring-context-4.0.xsd">
    <!--     1.包自动扫描: 凡是带有 @Controller @Service @Repository @Component     -->
    <context:component-scan base-package="com.jsxs"/>
    <!--    2.从外部环境中获取值 ⭐-->
    <context:property-placeholder location="classpath:person.properties"/>
    <!--   3. 通过Bean的方式进行我们的组件注入的操作  并设置作用域为多实例 -->
    <bean id="person" class="com.jsxs.bean.Person" scope="prototype">
    <!--    4.从外部环境中获取值使用EL表达式 ⭐⭐-->
        <property name="name" value="${person.name}"/>
        <property name="age" value="19"/>
    </bean>
</beans>

2.resource/beans.xml

person.name=李明

3.Person.java 实体类

package com.jsxs.bean;
import org.springframework.beans.factory.annotation.Value;
/**
 * @Author Jsxs
 * @Date 2023/8/11 19:57
 * @PackageName:com.jsxs.bean
 * @ClassName: Person
 * @Description: TODO
 * @Version 1.0
 */
public class Person {
    /**
     *  1.基本数值
     *  2. 可以写Spel表达式,#{}
     *  3.可以写${},取出配置文件中的值(即在运行环境中的值)
     *  通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,
     *  Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
     */
  //  ⭐⭐ 假如说这里加了@Value("${})注解也不会生效
    private String name;
    @Value("#{20-2}")
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

4.测试的操作

package com.jsxs.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
 * @Author Jsxs
 * @Date 2023/8/17 10:15
 * @PackageName:com.jsxs.Test
 * @ClassName: IOCTest_PropertyValue_anno
 * @Description: TODO
 * @Version 1.0
 */
public class IOCTest_PropertyValue_XML {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        System.out.println(applicationContext.getBean("person"));
    }
}

结果:我们取到了我们外部的文件,但是因为是中文,所以出现中文乱码的操作

(2).使用注解的方式 加载外部文件

1.Person.java

package com.jsxs.bean;
import org.springframework.beans.factory.annotation.Value;
/**
 * @Author Jsxs
 * @Date 2023/8/11 19:57
 * @PackageName:com.jsxs.bean
 * @ClassName: Person
 * @Description: TODO
 * @Version 1.0
 */
public class Person {
    /**
     *  1.基本数值
     *  2. 可以写Spel表达式,#{}
     *  3.可以写${},取出配置文件中的值(即在运行环境中的值)
     *  通过@PropertySource注解将properties配置文件中的值存储到Spring的 Environment中,
     *  Environment接口提供方法去读取配置文件中的值,参数是properties文件中定义的key值。
     */
  // ⭐⭐
    @Value("${person.name}")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;
    }
    public Person() {
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

2.配置文件 person.properties

person.name=asd

3.配置类

package com.jsxs.config;
import com.jsxs.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
/**
 * @Author Jsxs
 * @Date 2023/8/17 9:05
 * @PackageName:com.jsxs.config
 * @ClassName: MainConfigOfPropertyValues
 * @Description: TODO
 * @Version 1.0
 */
 // ⭐⭐ 配置文件不写了,但是我们需要在配置类上添加这个注解用来指定我们去哪个配置文件中进行获取数据
@PropertySource(value = {"classpath:person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
    @Bean
    public Person person() {
        return new Person();
    }
}

4.测试类

package com.jsxs.Test;
import com.jsxs.bean.Person;
import com.jsxs.config.MainConfigOfPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
 * @Author Jsxs
 * @Date 2023/8/17 9:07
 * @PackageName:com.jsxs.Test
 * @ClassName: IOCTest_PropertyValue
 * @Description: TODO
 * @Version 1.0
 */
public class IOCTest_PropertyValue {
    public static void main(String[] args) {
        // 1.创建IOC容器
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
        for (String beanDefinitionName : annotationConfigApplicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
        // 2.通过组件名获取具体的组件信息
        Person person = (Person)annotationConfigApplicationContext.getBean("person");
        System.out.println(person);
    }
}


目录
打赏
0
0
0
0
15
分享
相关文章
Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)
Spring 第三节 IOC——基于注解配置和管理Bean 万字详解!
198 26
SpringBoot缓存注解使用
Spring Boot 提供了一套方便的缓存注解,用于简化缓存管理。通过 `@Cacheable`、`@CachePut`、`@CacheEvict` 和 `@Caching` 等注解,开发者可以轻松地实现方法级别的缓存操作,从而提升应用的性能和响应速度。合理使用这些注解可以大大减少数据库的访问频率,优化系统性能。
223 89
Spring MVC常用的注解
@RequestMapping:用于处理请求 url 映射的注解,可用于类或方法上。用于类上,则表示类中 的所有响应请求的方法都是以该地址作为父路径。 @RequestBody:注解实现接收http请求的json数据,将json转换为java对象。 @ResponseBody:注解实现将conreoller方法返回对象转化为json对象响应给客户。 @Controller:控制器的注解,表示是表现层,不能用用别的注解代替 @RestController : 组合注解 @Conntroller + @ResponseBody @GetMapping , @PostMapping , @Put
Spring Boot的核心注解是哪个?他由哪几个注解组成的?
Spring Boot的核心注解是@SpringBootApplication , 他由几个注解组成 : ● @SpringBootConfiguration: 组合了- @Configuration注解,实现配置文件的功能; ● @EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项 ● @ComponentScan:Spring组件扫描
什么是Spring IOC 和DI ?
IOC : 控制翻转 , 它把传统上由程序代码直接操控的对象的调用权交给容 器,通过容器来实现对象组件的装配和管理。所谓的“控制反转”概念就是对组件对象控制权的转 移,从程序代码本身转移到了外部容器。 DI : 依赖注入,在我们创建对象的过程中,把对象依赖的属性注入到我们的类中。
SpringBoot+@Async注解一起用,速度提升
本文介绍了异步调用在高并发Web应用性能优化中的重要性,对比了同步与异步调用的区别。同步调用按顺序执行,每一步需等待上一步完成;而异步调用无需等待,可提升效率。通过Spring Boot示例,使用@Async注解实现异步任务,并借助Future对象处理异步回调,有效减少程序运行时间。
保姆级Spring AI 注解式开发教程,你肯定想不到还能这么玩!
这是一份详尽的 Spring AI 注解式开发教程,涵盖从环境配置到高级功能的全流程。Spring AI 是 Spring 框架中的一个模块,支持 NLP、CV 等 AI 任务。通过注解(如自定义 `@AiPrompt`)与 AOP 切面技术,简化了 AI 服务集成,实现业务逻辑与 AI 基础设施解耦。教程包含创建项目、配置文件、流式响应处理、缓存优化及多任务并行执行等内容,助你快速构建高效、可维护的 AI 应用。
【Spring】方法注解@Bean,配置类扫描路径
@Bean方法注解,如何在同一个类下面定义多个Bean对象,配置扫描路径
219 73
【SpringFramework】Spring IoC-基于XML的实现
本文主要讲解SpringFramework中IoC和DI相关概念,及基于XML的实现方式。
134 69
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
33 0