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); } }