129.【Spring 注解 IOC】

Spring 注解

  • (一)、组件注册
    • 1. @Configuration 与 @Bean 容器注册组件
        • (1).无注解注入方式
        • (2).注解注入方式
    • 2. @ComponentScan 自动扫描组件和自动扫描规则
        • (1).无注解扫描方式
        • (2).注解扫描注入方式
        • (3).指定扫描或不扫描的包 (过滤)
    • 3. 自定义TypeFilter指定过滤规则 @Filter
        • (1).自定义我们的扫描过滤器
    • 4.设置组件的作用域 @Scope
        • (1).组件默认是单实列
        • (2).修改为多实列 (注解)
        • (3).使用我们的XML文件进行实现多实列
    • 5.@Layz-bean懒加载
        • (1).懒加载
    • 6.@Conditional 按照条件注册bean
        • (1).按照一定的条件进行注册bean
    • 7.@Import给容器中快速导入一个组件
        • (1).@Import
        • (2).ImportSelector ⭐
        • (3). ImportBeanDefinitionRegistrar
        • (4).FactoryBean
  • (二)、组件的生命周期
    • 1.@Bean指定初始化和销毁方法
        • (1). 使用配置文件进行自定义我们的初始化方法和销毁方法 (==第一种==)
        • (2).通过@Bean注解进行初始化和销毁 (==第二种==)
    • 2.InitializingBean与 DisposableBean 进行初始化和销毁 (==第三种==)
        • (1).通过实现接口进行初始化和销毁的操作
    • 3.使用JSR250规范 (==第四种==)
        • (1).@PostConstruct 和 @PreDestroy
    • 4.BeanPostProcessor后置处理器 (==第五种==)
        • (1).BeanPostProcessor 后置处理器
    • 5.Spring底层对BeanPostProcessor的使用
        • (1). 【案例1】在实体类中获取ioc容器
  • (三)、属性赋值相关的注解
    • 1.@Value
        • (1).普通属性赋值 和 SPEL表达式赋值
    • 2. @PropertySource 加载外部配置文件
        • (1).使用配置文件的方式加载外部文件
        • (2).使用注解的方式 加载外部文件
  • (四)、自动装配
    • 1.@Autowired 自动装配
        • (1). 自动装配(原理是从IOC容器中获得值并赋值)
        • (2).@AutoWried(先类型后属性名)
        • (3).@Qualifier 配合 @AutoWried
        • (4).@Primary 首选装配
    • 2.@Resource 和 @Inject [JSR标准]
        • (1).@Resource 自动装配
        • (2).@Inject 自动装配
    • 3.@Autowried自动装配原理
        • (1).标注在Set方法位置上
        • (2).标注在有参构造方法上
        • (3).@Bean + 方法参数
    • 4.自定义组件使用Spring容器底层的一些组件
        • (1).xxxAware
    • 5.@Profile 切换多个应用场景
        • (1). 环境搭建
        • (2).根据环境注册bean (环境切换)

在这里插入图片描述

(一)、组件注册

1. @Configuration 与 @Bean 容器注册组件

(1).无注解注入方式

  1. 在pom文件中加入spring-context依赖
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>4.3.12.RELEASE</version>
</dependency>
  1. 定义一个实体类
package com.jsxs.bean;/*** @Author Jsxs* @Date 2023/8/11 19:57* @PackageName:com.jsxs.bean* @ClassName: Person* @Description: TODO* @Version 1.0*/
public class Person {private String name;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;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +'}';}
}
  1. 在resource目录下的beans.xml配置文件中通过< bean>< /bean>标签注入类实例
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--  通过Bean的方式进行我们的组件注入的操作  --><bean id="person" class="com.jsxs.bean.Person"><property name="name" value="李明"></property><property name="age" value="19"></property></bean>
</beans>
  1. 获取容器中通过配置文件注入的实例对象
package com.jsxs;import com.jsxs.bean.Person;
import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @Author Jsxs* @Date 2023/8/11 20:14* @PackageName:com.jsxs* @ClassName: MainTest* @Description: TODO* @Version 1.0*/
public class MainTest {public static void main(String[] args) {// 通过配置文件,创建ioc容器,并向容器中注入实列对象ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");// 根据bean的id获取容器中注入的实列对象Person person = (Person)applicationContext.getBean("person");System.out.println(person);}
}

在这里插入图片描述

(2).注解注入方式

1.MyConfig.java

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/12 9:05* @PackageName:com.jsxs.config* @ClassName: MyConfig* @Description: TODO* @Version 1.0*/@Configuration
public class MyConfig {@Beanpublic Person person(){return new Person("李三",21);}
}

2.Main.java

package com.jsxs;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/12 9:07* @PackageName:com.jsxs* @ClassName: Main* @Description: TODO* @Version 1.0*/
public class Main {public static void main(String[] args) {// 读取通过配置类,创建ioc容器,并向容器中注入实例对象AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);Person person = (Person)applicationContext.getBean("person");System.out.println(person);}
}

在这里插入图片描述

2. @ComponentScan 自动扫描组件和自动扫描规则

(1).无注解扫描方式

只要我们加上 @Configuration 这个注解,这个类就会默认加入IOC容器。

  1. 设置三个组件,并通过包扫描的方式进行注入我们的容器。
package com.jsxs.Mapper;import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository
public class BookMapper {
}
package com.jsxs.service;import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {}
package com.jsxs.controller;import org.springframework.stereotype.Controller;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.controller* @ClassName: BookController* @Description: TODO* @Version 1.0*/
@Controller
public class BookController {
}

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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd"><!-- 包自动扫描: 凡是带有 @Controller @Service @Repository @Component     --><context:component-scan base-package="com.jsxs"/><!--  通过Bean的方式进行我们的组件注入的操作  --><bean id="person" class="com.jsxs.bean.Person"><property name="name" value="李明"/><property name="age" value="19"/></bean></beans>

2.IOCTest.java

package com.jsxs.Test;import org.springframework.context.support.ClassPathXmlApplicationContext;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Test* @ClassName: IOCTest* @Description: TODO* @Version 1.0*/
public class IOCTest {public static void main(String[] args) {// 读取通过配置文件注入容器中实列ClassPathXmlApplicationContext applicationContext = new   ClassPathXmlApplicationContext("beans.xml");// 进行遍历的操作for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
}

在这里插入图片描述

(2).注解扫描注入方式

MyConfig.java 带有@Configuration的注解一开始就会被默认加入我们的组件中去。

package com.jsxs.config;import com.jsxs.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @Author Jsxs* @Date 2023/8/12 9:05* @PackageName:com.jsxs.config* @ClassName: MyConfig* @Description: TODO* @Version 1.0*/
@ComponentScan(value = "com.jsxs")
@Configuration
public class MyConfig {@Beanpublic Person person(){return new Person("李三",21);}
}

在这里插入图片描述

(3).指定扫描或不扫描的包 (过滤)

  1. 使用 @ComponentScan 进行操作扫描包 - (排除xxx)
package com.jsxs.config;import com.jsxs.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.FilterType;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:05* @PackageName:com.jsxs.config* @ClassName: MyConfig* @Description: TODO* @Version 1.0*/// 指定扫描com.jsxs这个包下面的全部文件,但是排除掉注解为 Controller 和 Service 的组件
@ComponentScan(value = "com.jsxs",excludeFilters = {  // 这里是排除掉xxx@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class,Service.class})})
@Configuration
public class MyConfig {@Beanpublic Person person() {return new Person("李三", 21);}
}

结果我们发现: 我们IOC容器中的组件中少我们指定的Controller 和 Service 这两个组件标注的组件
在这里插入图片描述

  1. 使用 @ComponentScans 进行扫描多个 @ComponentScan (不排除xxx)
package com.jsxs.config;import com.jsxs.bean.Person;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:05* @PackageName:com.jsxs.config* @ClassName: MyConfig* @Description: TODO* @Version 1.0*/// 这里可以通过 @ComponentScans 配置多个 @@ComponentScan@ComponentScans(value = {
// 指定扫描com.jsxs这个包下面的全部文件,但是排除掉注解为 Controller 和 Service 的组件@ComponentScan(value = "com.jsxs",includeFilters = {  // 这里是只有包含这些组件的才被打印出来@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class, Service.class})}, useDefaultFilters = false)  // 这里就相当于把所有的非includeFilters全部过滤掉,不显示(默认为true)})@Configuration
public class MyConfig {@Beanpublic Person person() {return new Person("李三", 21);}
}

我们发现我们的结果 只有我们通过配置
在这里插入图片描述

3. 自定义TypeFilter指定过滤规则 @Filter

(1).自定义我们的扫描过滤器

在这里插入图片描述
1. 过滤的文件是这样写的

package com.jsxs.config;import org.springframework.core.io.Resource;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;import java.io.IOException;/*** @Author Jsxs* @Date 2023/8/12 19:57* @PackageName:com.jsxs.config* @ClassName: MyTypeFilter* @Description: TODO  自定义过滤的话,我们需要实现这个 TypeFilter 接口* @Version 1.0*/
public class MyTypeFilter implements TypeFilter { //⭐/**** @param metadataReader  : 读取当前正在扫描的类* @param metadataReaderFactory : 可以获取到其他任何类的信息* @return* @throws IOException*/@Overridepublic boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {// 1.获取当前类注解的信息AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();// 2.获取当前正在扫描的类的类信息ClassMetadata classMetadata = metadataReader.getClassMetadata();// 3.获取当前类资源(类路径)Resource resource = metadataReader.getResource();// 4.获取当前类的类名String className = classMetadata.getClassName();System.out.println("---> "+className);// 5.假如 类名中存在 er 的话,我们就将这个容器注入到组件中去if (className.contains("er")){return true;}return false;}
}

2. 配置文件是这样写的

package com.jsxs.config;import com.jsxs.Mapper.BookMapper;
import com.jsxs.bean.Person;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.*;
import org.springframework.stereotype.Controller;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:05* @PackageName:com.jsxs.config* @ClassName: MyConfig* @Description: TODO* @Version 1.0*//***  TODO: 1. ANNOTATION 按照注解 ; 2.  ASSIGNABLE_TYPE 按照给定的类型 3.CUSTOM 自定义规则*/
// 1. 这里是一个数组,可以包含多个@ComponentScan
@ComponentScans(value = {//  2. 指定扫描com.jsxs这个包下面的全部文件,但是排除掉注解为 Controller 和 Service 的组件@ComponentScan(value = "com.jsxs",// 3. 这里是一个数组,可以包含多个 FilterincludeFilters = {  // 4. 这里是只有包含这些组件的才被打印出来// 4.1 第一个Filter ⭐@ComponentScan.Filter( // 5. 类型是注解 ; 要过滤的类文件type = FilterType.ANNOTATION, classes = {Controller.class, Service.class}),// 4.2 第二个Filter ⭐@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {BookMapper.class}),// 4.3 第三个Filter ⭐@ComponentScan.Filter(  // 5.指向我们自定义的过滤类信息type = FilterType.CUSTOM,classes = {MyTypeFilter.class})}, useDefaultFilters = false)  // 这里就相当于把所有的非includeFilters全部过滤掉,不显示})
@Configuration
public class MyConfig {@Beanpublic Person person() {return new Person("李三", 21);}
}

在这里插入图片描述

4.设置组件的作用域 @Scope

(1).组件默认是单实列

组件默认在IOC容器中是单实列的,也就是说我们在IOC容器中使用的组件都是同一个组件。
1. 进行编写我们的配置文件

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/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
public class MyConfig2 {@Bean("person2")public Person person(){return new Person("张三2",22);}
}

2.测试类

package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.通过我们的组件名获取我们指定的组件信息Person person = (Person)applicationContext.getBean("person2");Person person2 = (Person)applicationContext.getBean("person2");// 3.打印出我们的组件信息System.out.println(person);// 4.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}// 5.组件默认是单实列的 即 在IOC容器中,我们一直使用的都是同一个组件System.out.println("判断是否是一个单实列的,结果是:"+(person2==person));}
}

在这里插入图片描述

(2).修改为多实列 (注解)

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.Scope;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
public class MyConfig2 {/**  1. singleton 但是列的*   2.prototype 多实列   (默认值)*   3. 同一次请求创建一个实列*   4. 同一个session创建一个实列*/@Scope(value = "prototype")  // ⭐ 我们这在里修改为多实列的@Bean("person2")public Person person(){return new Person("张三2",22);}
}
package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.通过我们的组件名获取我们指定的组件信息Person person = (Person)applicationContext.getBean("person2");Person person2 = (Person)applicationContext.getBean("person2");// 3.打印出我们的组件信息System.out.println(person);// 4.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}// 5.组件默认是单实列的 即 在IOC容器中,我们一直使用的都是同一个组件  ⭐System.out.println("判断是否是一个单实列的,结果是:"+(person2==person));}
}

在这里插入图片描述

(3).使用我们的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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-4.0.xsd"><!--     包自动扫描: 凡是带有 @Controller @Service @Repository @Component     --><context:component-scan base-package="com.jsxs"/><!--  通过Bean的方式进行我们的组件注入的操作  --><bean id="person" class="com.jsxs.bean.Person" scope="prototype"><property name="name" value="李明"/><property name="age" value="19"/></bean></beans>

在这里插入图片描述
小结: 我们使用多实列的情况下,我们的组件并不会在IOC创建完成的时候进创建我们的实列,而是当我们使用到组件的时候,才会帮助我们创建我们的实列。 (懒汉式)

单实列: 我们的组件会在我们的容器创建完成之后就会帮助我们创建我们的实列。 (饿汉式)

5.@Layz-bean懒加载

(1).懒加载

单实例bean,默认在容器创建启动的时候就会创建对象。但是在懒加载模式下,容器启动的时候不会创建对象,而是在第一次使用(获取)Bean的时候才会创建并初始化。

单实列 + 懒加载 ≠ 多实例
1. 设置配置类的组件为 单实列+懒加载

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.Lazy;
import org.springframework.context.annotation.Scope;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
public class MyConfig2 {/**  1. singleton 但是列的*   2.prototype 多实列   (默认值)*   3. 同一次请求创建一个实列*   4. 同一个session创建一个实列*/@Scope(value = "prototype")  //⭐@Bean("person2")@Lazy  //⭐public Person person(){return new Person("张三2",22);}
}

2.进行测试

package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.通过我们的组件名获取我们指定的组件信息Person person = (Person)applicationContext.getBean("person2");Person person2 = (Person)applicationContext.getBean("person2");// 3.打印出我们的组件信息System.out.println(person);// 4.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}// 5.组件默认是单实列的 即 在IOC容器中,我们一直使用的都是同一个组件System.out.println("判断是否是一个单实列的,结果是:"+(person2==person));}
}

因为懒加载的意思就是当我们使用的时候才回去创建实列,又因为是单实列的所以我们只会创建一次
在这里插入图片描述

6.@Conditional 按照条件注册bean

(1).按照一定的条件进行注册bean

按照一定的条件进行判断,满足条件时才给容器中注册bean。

这里我们要实现 condition 的接口,因为我们的@Conditional({参数}),这里的参数就是我们需要继承 condition 的接口。
WindowConditional.java

package com.jsxs.conditional;import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;/*** @Author Jsxs* @Date 2023/8/13 19:18* @PackageName:com.jsxs.conditional* @ClassName: WindowConditional* @Description: TODO* @Version 1.0*/
public class WindowConditional implements Condition {  //⭐/**** @param context : 可以获取到上下文* @param metadata : 注解* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {Environment environment = context.getEnvironment();if (environment.getProperty("os.name").contains("Windows")){return true;}return false;}
}

LinuxConditional.java

package com.jsxs.conditional;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.Condition;
import org.springframework.context.annotation.ConditionContext;
import org.springframework.core.env.Environment;
import org.springframework.core.type.AnnotatedTypeMetadata;/*** @Author Jsxs* @Date 2023/8/13 19:18* @PackageName:com.jsxs.conditional* @ClassName: LinuxConditional* @Description: TODO  我们需要继承Condition这个接口* @Version 1.0*/
public class LinuxConditional implements Condition {  //⭐/**** @param context : 判断条件能使用的上下文(环境)* @param metadata : 注释信息* @return*/@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 1. 能获取到IOC使用的beanFactoryConfigurableListableBeanFactory beanFactory = context.getBeanFactory();// 2. 能获取到类加载器ClassLoader classLoader = context.getClassLoader();// 3. 获取我们的开发环境Environment environment = context.getEnvironment();// 4.获取到bean定义的注册类BeanDefinitionRegistry registry = context.getRegistry();if (environment.getProperty("os.name").contains("Linux")){return true;}return false;}
}

MyConfig2.java

package com.jsxs.config;import com.jsxs.bean.Person;
import com.jsxs.conditional.LinuxConditional;
import com.jsxs.conditional.WindowConditional;
import org.springframework.context.annotation.*;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
public class MyConfig2 {/*@ conditional({condition列表}) 按照条件进行注入我们的组件提出需求:  假如我们的系统是window系统的话,那么我们就注册 person01 这个组件,如果是linux系统的话 我们就注册 person02 这个组件。*/@Conditional({WindowConditional.class})  //⭐@Bean("person01")public Person person01(){return new Person("张三01",33);}@Conditional(LinuxConditional.class)  // ⭐@Bean("person02")public Person person02(){return new Person("张三02",33);}
}

在这里插入图片描述

7.@Import给容器中快速导入一个组件

这个注解需要放在我们的配置类上,因为配置类项目刚启动的时候就会加载进组件,我们IOC需要识别到这个 @Import 才能继续工作。

    /***  给容器中注册组件*  1. 包扫描 + 组件标注注解 (repository,service controller component)*  2. @Configuration + @Bean*  3. @Import[快速给容器导入一个组件]* 		(1).@Import(要导入的容器),容器中会自动注册这个组件,id默认是全限定名。* 		(2).@ImportSelector: 返回需要导入的组件的全限定名数组。*  4.FactoryBean: 使用Spring提供的FactoryBean (工厂Bean)*/

(1).@Import

1.要注册的组件

package com.jsxs.bean;/*** @Author Jsxs* @Date 2023/8/13 20:54* @PackageName:com.jsxs.bean* @ClassName: Color* @Description: TODO* @Version 1.0*/
public class Color {
}

2.@Import注解放在类上

package com.jsxs.config;import com.jsxs.bean.Color;
import com.jsxs.bean.Person;
import com.jsxs.conditional.LinuxConditional;
import com.jsxs.conditional.WindowConditional;
import org.springframework.context.annotation.*;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
// 快速的导入组件,id默认的是全限定名 ⭐
@Import(Color.class)
public class MyConfig2 {/*** 1. singleton 但是列的* 2.prototype 多实列   (默认值)* 3. 同一次请求创建一个实列* 4. 同一个session创建一个实列*/@Scope(value = "singleton")@Bean("person2")@Lazypublic Person person() {return new Person("张三2", 22);}/*@ conditional({condition列表}) 按照条件进行注入我们的组件提出需求:  假如我们的系统是window系统的话,那么我们就注册 person01 这个组件,如果是linux系统的话 我们就注册 person02 这个组件。*/@Conditional({WindowConditional.class})@Bean("person01")public Person person01() {return new Person("张三01", 33);}@Conditional(LinuxConditional.class)@Bean("person02")public Person person02() {return new Person("张三02", 33);}}

3.测试

package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.我们可以通过IOC容器获取我们的运行环境,然后获取我们的系统环境ConfigurableEnvironment environment = applicationContext.getEnvironment();System.out.println(environment.getSystemEnvironment());// 3.获取我们具体的属性名System.out.println(environment.getProperty("os.name"));// 2.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
}

在这里插入图片描述

(2).ImportSelector ⭐

假如我们的类实现了 ImportSelector 的接口,那么我们这个类的返回值就是我们需要注入IOC容器中组件的全限定名。.

在这里插入图片描述
1.MyImportSelector.java

package com.jsxs.conditional;import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;/*** @Author Jsxs* @Date 2023/8/13 21:07* @PackageName:com.jsxs.conditional* @ClassName: MyImportSelector* @Description: TODO   自定义逻辑返回需要导入的组件* @Version 1.0*/
public class MyImportSelector implements ImportSelector {/**** @param importingClassMetadata :  当前标注@Import注解的类的所有注解信息* @return : 返回值就是导入容器中的组件全类名*/@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.jsxs.bean.Yellow","com.jsxs.bean.Red"};  // ⭐}
}
package com.jsxs.config;import com.jsxs.bean.Color;
import com.jsxs.bean.Person;
import com.jsxs.conditional.LinuxConditional;
import com.jsxs.conditional.MyImportSelector;
import com.jsxs.conditional.WindowConditional;
import org.springframework.context.annotation.*;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
// 快速的导入组件,id默认的是全限定名   ⭐⭐
@Import({Color.class, MyImportSelector.class})public class MyConfig2 {/*** 1. singleton 但是列的* 2.prototype 多实列   (默认值)* 3. 同一次请求创建一个实列* 4. 同一个session创建一个实列*/@Scope(value = "singleton")@Bean("person2")@Lazypublic Person person() {return new Person("张三2", 22);}/*@ conditional({condition列表}) 按照条件进行注入我们的组件提出需求:  假如我们的系统是window系统的话,那么我们就注册 person01 这个组件,如果是linux系统的话 我们就注册 person02 这个组件。*/@Conditional({WindowConditional.class})@Bean("person01")public Person person01() {return new Person("张三01", 33);}@Conditional(LinuxConditional.class)@Bean("person02")public Person person02() {return new Person("张三02", 33);}/***  给容器中注册组件*  1. 包扫描 + 组件标注注解 (repository,service controller component)*  2. @Configuration + @Bean*  3. @Import*/
}

在这里插入图片描述

(3). ImportBeanDefinitionRegistrar

在这里插入图片描述
1.我们需要实现一个接口 ImportBeanDefinitionRegistrar

package com.jsxs.conditional;import com.jsxs.bean.RainBow;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;/*** @Author Jsxs* @Date 2023/8/14 8:44* @PackageName:com.jsxs.conditional* @ClassName: MyImportBeanDefinitionRegistrar* @Description: TODO* @Version 1.0*/
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {/**** @param importingClassMetadata : 当前类的注解信息* @param registry : BeanDefinition注册类*/@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 1.先判断我们的容器中是否有有我们将要注入IOC容器的组件if (registry.containsBeanDefinition("com.jsxs.bean.Color")) {// 第一个参数是我们注册后的组件名叫什么,第二个参数是我们需要使用类的全限定名 ⭐registry.registerBeanDefinition("RainBow",new RootBeanDefinition(RainBow.class));}}
}

2. 配置类编写

package com.jsxs.config;import com.jsxs.bean.Color;
import com.jsxs.bean.Person;
import com.jsxs.conditional.LinuxConditional;
import com.jsxs.conditional.MyImportBeanDefinitionRegistrar;
import com.jsxs.conditional.MyImportSelector;
import com.jsxs.conditional.WindowConditional;
import org.springframework.context.annotation.*;/*** @Author Jsxs* @Date 2023/8/12 20:20* @PackageName:com.jsxs.config* @ClassName: MyConfig2* @Description: TODO* @Version 1.0*/
@Configuration
// 快速的导入组件,id默认的是全限定名  ⭐⭐
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})public class MyConfig2 {/*** 1. singleton 但是列的* 2.prototype 多实列   (默认值)* 3. 同一次请求创建一个实列* 4. 同一个session创建一个实列*/@Scope(value = "singleton")@Bean("person2")@Lazypublic Person person() {return new Person("张三2", 22);}/*@ conditional({condition列表}) 按照条件进行注入我们的组件提出需求:  假如我们的系统是window系统的话,那么我们就注册 person01 这个组件,如果是linux系统的话 我们就注册 person02 这个组件。*/@Conditional({WindowConditional.class})@Bean("person01")public Person person01() {return new Person("张三01", 33);}@Conditional(LinuxConditional.class)@Bean("person02")public Person person02() {return new Person("张三02", 33);}}

3.进行测试的操作

package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.我们可以通过IOC容器获取我们的运行环境,然后获取我们的系统环境ConfigurableEnvironment environment = applicationContext.getEnvironment();System.out.println(environment.getSystemEnvironment());// 3.获取我们具体的属性名System.out.println(environment.getProperty("os.name"));// 2.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
}

在这里插入图片描述

(4).FactoryBean

第四种在IOC容器中注入我们的组件的方法就是 我们Spring提供的 FactoryBean 工厂。我们只需要实现接口 FactoryBean< T> 这里的 T 就是我们需要的被注入IOC容器的组件类名称。

1. 实际要被注入IOC容器的类

package com.jsxs.bean;/*** @Author Jsxs* @Date 2023/8/14 9:53* @PackageName:com.jsxs.bean* @ClassName: Color_factory* @Description: TODO* @Version 1.0*/
public class Color_factory {
}

2.实现我们的接口

package com.jsxs.bean;import org.springframework.beans.factory.FactoryBean;/*** @Author Jsxs* @Date 2023/8/14 9:15* @PackageName:com.jsxs.bean* @ClassName: ColorFactoryBean* @Description: TODO* @Version 1.0*/// 创建一个Spring定义的FactoryBean  ⭐
public class ColorFactoryBean implements FactoryBean<Color_factory> {  // 这里我们指定我们的类型T为 我们想要注册的组件// 1.返回一个 ColorFactoryBean 对象,这个对象会添加到容器中去 ⭐@Overridepublic Color_factory getObject() throws Exception {return new Color_factory();}// 2.返回类的类型  ⭐@Overridepublic Class<?> getObjectType() {return Color_factory.class;}// 3. 是否是单列? ⭐/**** @return : 假如说为true,那么我们就是单实列的,假如说为false,那么我们就不是单实列的。*/@Overridepublic boolean isSingleton() {return false;}
}

3.配置类中注册我们的ColorFactoryBean

    @Beanpublic ColorFactoryBean colorFactoryBean(){return new ColorFactoryBean();}

4.测试输出

package com.jsxs.Test;import com.jsxs.bean.Person;
import com.jsxs.config.MyConfig2;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.core.env.ConfigurableEnvironment;/*** @Author Jsxs* @Date 2023/8/12 20:22* @PackageName:com.jsxs.Test* @ClassName: Main_Ann2* @Description: TODO* @Version 1.0*/
public class Main_Ann2 {public static void main(String[] args) {// 1.将这个配置文件中的组件放入我们的IOC容器中AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig2.class);// 2.我们可以通过IOC容器获取我们的运行环境,然后获取我们的系统环境ConfigurableEnvironment environment = applicationContext.getEnvironment();System.out.println(environment.getSystemEnvironment());// 3.获取我们具体的属性名System.out.println(environment.getProperty("os.name"));// 2.遍历我们所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}System.out.println(applicationContext.getBean("colorFactoryBean")+"-----");}
}

遍历所有组件,我们只会得到表象为 colorFactory 这个组件。实际上我们通过组件的名字获取这个colorFactory便会得到我们实际上注入组件的类型和名字。

com.jsxs.bean.Color_factory@276438c9 这个是实际上注入的组件
在这里插入图片描述

(二)、组件的生命周期

1.@Bean指定初始化和销毁方法

(1). 使用配置文件进行自定义我们的初始化方法和销毁方法 (第一种)

在这里插入图片描述

(2).通过@Bean注解进行初始化和销毁 (第二种)

  1. 当对象创建完成后,并赋值好之后,调用初始化方法。
  2. 容器关闭之后,调用销毁的方法
 * Bean的生命周期*                      bean 创建 -> 初始化 -> 销毁的过程*                      容器管理bean的生命周期; 我们可以自定义生命周期中的 初始化环节和销毁的环节。容器在bean运行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。*                      1. init-method="" destroy-method=""*                      2. 构造(对象创建)*                          单实列: 在容器启动的时候创建对象*                          多实列: 在调用到组件的时候创建对象

1.Car.java

package com.jsxs.bean;/*** @Author Jsxs* @Date 2023/8/14 17:12* @PackageName:com.jsxs.bean* @ClassName: Car* @Description: TODO* @Version 1.0*/
public class Car {public Car(){System.out.println("Car Constructor ....");}public void init(){System.out.println("Car Init...");}public void destroy(){System.out.println("Car Destroy...");}
}

2.配置类

package com.jsxs.config;import com.jsxs.bean.Car;
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();}
}

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

在这里插入图片描述

2.InitializingBean与 DisposableBean 进行初始化和销毁 (第三种)

(1).通过实现接口进行初始化和销毁的操作

1.我们需要自定义的bean只需要实现两个接口InitializingBean, DisposableBean即可

package com.jsxs.bean;import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;/*** @Author Jsxs* @Date 2023/8/14 19:57* @PackageName:com.jsxs.bean* @ClassName: Car01* @Description: TODO* @Version 1.0*/
public class Car01 implements InitializingBean, DisposableBean {public Car01() {}// 1.初始化的操作@Overridepublic void afterPropertiesSet() throws Exception {System.out.println("Car01进行初始化...");}// 2.销毁的操作@Overridepublic void destroy() throws Exception {System.out.println("Car01进行销毁...");}
}
package com.jsxs.config;import com.jsxs.bean.Car;
import com.jsxs.bean.Car01;
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 {@Beanpublic Car01 car01() {return new Car01();}
}

在这里插入图片描述

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...");}@PostConstructpublic 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();}@Beanpublic Car01 car01() {return new Car01();}@Beanpublic 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*/@Componentpublic 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();}@Beanpublic Car01 car01() {return new Car01();}@Beanpublic 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...");}@PostConstructpublic 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;}@Overridepublic 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 {@Beanpublic 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/beanshttp://www.springframework.org/schema/beans/spring-beans-4.0.xsdhttp://www.springframework.org/schema/contexthttp://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;}@Overridepublic 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;}@Overridepublic 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 {@Beanpublic 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);}
}

在这里插入图片描述

(四)、自动装配

什么是自动装配?

Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值

1.@Autowired 自动装配

/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 比如: applicationContext.getBean("bookMapper") 通过具体组件名获取*  (3).如果想指定使用某一个同类型不同命的组件,那么需要使用 @Qualifier("book2") 进行指定需要的组件* @Version 1.0*/

(1). 自动装配(原理是从IOC容器中获得值并赋值)

1.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

2.BookService.java

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {//  ⭐⭐@Autowiredprivate BookMapper bookMapper;public void print(){System.out.println("1111111111111111111"+bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

3.配置类的书写

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 applicationContext.getBean("bookMapper")* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")  // ⭐⭐
public class MainConfigOfAutowried {}

4.测试

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}// 判断我们是否是从IOC容器中获得值并赋值?BookMapper bean = applicationContext.getBean(BookMapper.class);BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);System.out.println(bean);}
}

在这里插入图片描述

(2).@AutoWried(先类型后属性名)

这里我们第一个组件通过 @Reposity 注解扫描注入IOC容器,然后第二个组件通过 @Bean 的方式注入IOC容器。所以在这里我们就会发现在同一个IOC容器中有两个相同类型但不同名的组件。

1.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/// 组件1
@Repository
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

2.BookService.java

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {@Autowiredprivate BookMapper bookMapper;public void print(){System.out.println(bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 applicationContext.getBean("bookMapper")* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")
public class MainConfigOfAutowried {// ⭐ 通过@Bena注入的同类型不同命组件@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试类

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);}
}

证明在同一个IOC容器中有两个相同类型但不同名的组件。
在这里插入图片描述
在这里插入图片描述

(3).@Qualifier 配合 @AutoWried

假如我们注入一个组件并未指定他的组件名,那么组件名就会默认是 首字母小写的驼峰命名。所以使用这个组件的目的主要是为了解决 相同类型但不同组件名 的需求。

1.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository  // ⭐组件一
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

2.BookService.java

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {@Autowired  // ⭐ 自动装配@Qualifier("book2") // 指定名字private BookMapper bookMapper;public void print(){System.out.println(bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 比如: applicationContext.getBean("bookMapper") 通过具体组件名获取*  (3).如果想指定使用某一个同类型不同命的组件,那么需要使用 @Qualifier("book2") 进行指定需要的组件* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")  // ⭐扫描
public class MainConfigOfAutowried {@Bean("book2")  // ⭐⭐ 组件二public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);}
}

在这里插入图片描述

(4).@Primary 首选装配

常用于: 相同类型不同名的组件,然后相比于 @Quailfier() 的使用是 在使用组件的时候添加,@Primary是在组件创建的时候,就默认未首选装配。
1.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

2.BookService

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {@Autowired
//    @Qualifier("book2")  ⭐⭐ 这里我们不指定使用哪个具体名字的组件进行装配private BookMapper bookMapper;public void print(){System.out.println("1111111111111111111"+bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 比如: applicationContext.getBean("bookMapper") 通过具体组件名获取*  (3).如果想指定使用某一个同类型不同命的组件,那么需要使用 @Qualifier("book2") 进行指定需要的组件*  (4).@Qualifier("book2")需要在使用的时候加入注解,比较繁琐,我们希望在注册组件的时候就作为首选组件 @Primary* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")
public class MainConfigOfAutowried {@Primary   // ⭐⭐⭐ 组件在注册的时候,我们就指定使用这个组件进行装配 同类型不同组件命的组件@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);}
}

在这里插入图片描述

2.@Resource 和 @Inject [JSR标准]

Spring 还支持@Resource(JSR250) 和 @Inject(JSR330) [Java 规范]

(1).@Resource 自动装配

1.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

2.BookServer.java

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;import javax.annotation.Resource;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {// ⭐⭐假如需要指定具体的组件的话,我们需要添加name属性,如果不添加name属性的话,就默认按照变量名查找 applicationContext.getBean("bookMapper")@Resource(name = "book2")private BookMapper bookMapper;public void print(){System.out.println("1111111111111111111"+bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 比如: applicationContext.getBean("bookMapper") 通过具体组件名获取*  (3).如果想指定使用某一个同类型不同命的组件,那么需要使用 @Qualifier("book2") 进行指定需要的组件*  (4).@Qualifier("book2")需要在使用的时候加入注解,比较繁琐,我们希望在注册组件的时候就作为首选组件 @Primary**  2. @Resource: 自动注入 ⭐⭐*  (1).@Resource和@Autowried都可以对IOC容器的组件进行自动装配,但是@Autowried是按照组件的类型和名称进行自动装配的*  (2).@Resource不能支持@Primary和@Quailifer这两个注解*  3. @Inject: 自动注入*  (1).能够支持@Primary和@Quailifer , 和 @Autowired一样*  (2).但是需要导入一个包* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")
public class MainConfigOfAutowried {@Primary  // ⭐⭐ 这个添加是没有用的,因为@Resource不支持@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试类

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);}
}

在这里插入图片描述

(2).@Inject 自动装配

1.导入对应的 inject依赖

<dependency><groupId>javax.inject</groupId><artifactId>javax.inject</artifactId><version>1</version>
</dependency>

2.BookMapper.java

package com.jsxs.mapper;import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/12 9:39* @PackageName:com.jsxs.Mapper* @ClassName: BookMapper* @Description: TODO* @Version 1.0*/
@Repository
public class BookMapper {private String label="1";public String getLabel() {return label;}public void setLabel(String label) {this.label = label;}@Overridepublic String toString() {return "BookMapper{" +"label='" + label + '\'' +'}';}
}

3.BookService.java

package com.jsxs.service;import com.jsxs.mapper.BookMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.inject.Inject;/*** @Author Jsxs* @Date 2023/8/12 9:33* @PackageName:com.jsxs.service* @ClassName: BookService* @Description: TODO* @Version 1.0*/@Service
public class BookService {// @Inject 和 @Autowried 一模一样。 可以使用@Quailifer 和 @Primary ⭐⭐@Injectprivate BookMapper bookMapper;public void print(){System.out.println("1111111111111111111"+bookMapper);}@Overridepublic String toString() {return "BookService{" +"bookMapper=" + bookMapper +'}';}
}

4.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO* 自动装配:* Spring利用依赖注入(DI),完成对IOC容器中各个组件的依赖关系赋值* 1. @Autowired:自动注入* 原理:假如我们service类需要用到dao类那么我们在service中声明 dao类为私有变量并加上@Autowired注解*  (1).那么默认按照类型去容器中找对应的组件: 好比如:  applicationContext.getBean(BookMapper.class); 假如找到一个的话,那么就从IOC容器中取值并赋值*  (2).如果找到多个相同类型的组件,再将属性的名称作为的id去容器中查找。 比如: applicationContext.getBean("bookMapper") 通过具体组件名获取*  (3).如果想指定使用某一个同类型不同命的组件,那么需要使用 @Qualifier("book2") 进行指定需要的组件*  (4).@Qualifier("book2")需要在使用的时候加入注解,比较繁琐,我们希望在注册组件的时候就作为首选组件 @Primary**  2. @Resource: 自动注入*  (1).@Resource和@Autowried都可以对IOC容器的组件进行自动装配,但是@Autowried是按照组件的类型和名称进行自动装配的*  (2).@Resource不能支持@Primary和@Quailifer这两个注解*  3. @Inject: 自动注入 ⭐⭐*  (1).能够支持@Primary和@Quailifer , 和 @Autowired一样*  (2).但是需要导入一个包* @Version 1.0*/@Configuration
@ComponentScan(value = "com.jsxs")
public class MainConfigOfAutowried {@Primary  // ⭐⭐⭐ 可以使用@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

5.测试

package com.jsxs.Test;import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}BookService bean1 = applicationContext.getBean(BookService.class);System.out.println(bean1);}
}

在这里插入图片描述

3.@Autowried自动装配原理

在这里插入图片描述

通过点击 @Autowried的源码,我们发现这个注解可以标注在构造器上方法上等。

(1).标注在Set方法位置上

    // 标注在方法上,Spring容器创建当前对象,就会调用方法,完成赋值的操作。// 方法使用的参数,自定义类型的参数的值是从IOC容器中获取, 比如说 我们启动IOC容器后,就会在IOC容器中找类型未 Car.class 类型的组件

如果需要自动装配的话,项目要求非要方法上的话,那么一定要优先选择 set 方法
1. Car.java

package com.jsxs.bean;import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/14 17:12* @PackageName:com.jsxs.bean* @ClassName: Car* @Description: TODO* @Version 1.0*/@Repositorypublic class Car {public Car(){System.out.println("Car Constructor ....");}public void init(){System.out.println("Car Init...");}public void destroy(){System.out.println("Car Destroy...");}
}

2.Boss.java

package com.jsxs.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/17 17:34* @PackageName:com.jsxs.bean* @ClassName: Boss* @Description: TODO* @Version 1.0*/@Repository  ⭐⭐
public class Boss {private Car car;public Boss(Car car) {this.car = car;}public Boss() {}public Car getCar() {return car;}@Autowired  ⭐⭐⭐// 标注在方法上,Spring容器创建当前对象,就会调用方法,完成赋值的操作。// 方法使用的参数,自定义类型的参数的值是从IOC容器中获取, 比如说 我们启动IOC容器后,就会在IOC容器中找类型未 Car.class 类型的组件public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Boss{" +"car=" + car +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO**/@Configuration
@ComponentScan(value = "com.jsxs")  //⭐⭐⭐ 扫描
public class MainConfigOfAutowried {@Primary@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试

package com.jsxs.Test;import com.jsxs.bean.Boss;
import com.jsxs.bean.Car;
import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}// 判断是否是是在IOC容器中获取的Boss bean = applicationContext.getBean(Boss.class);Car bean1 = applicationContext.getBean(Car.class);System.out.println(bean);System.out.println(bean1);}
}

在这里插入图片描述

(2).标注在有参构造方法上

创建对象默认是调用无参构造方法的,但是因为我们在有参构造方法上添加了@Autowried,那么我们就会在IOC创建后,创建对象的话就会使用有参构造函数进行创建了。
1.Car.java

package com.jsxs.bean;import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/14 17:12* @PackageName:com.jsxs.bean* @ClassName: Car* @Description: TODO* @Version 1.0*/@Repository
public class Car {public Car(){System.out.println("Car Constructor ....");}public void init(){System.out.println("Car Init...");}public void destroy(){System.out.println("Car Destroy...");}
}

2.Boss.java

package com.jsxs.bean;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;/*** @Author Jsxs* @Date 2023/8/17 17:34* @PackageName:com.jsxs.bean* @ClassName: Boss* @Description: TODO* @Version 1.0*/@Repository  //⭐扫描后默认加载IOC容器中的组件,容器启动就会(单实列饿汉)调用无参构造器创建对象,再进行初始化赋值等操作。⭐
public class Boss {private Car car;@Autowired ⭐⭐// 标注在方法上,Spring容器创建当前对象,就会调用方法,完成赋值的操作。// 方法使用的参数,自定义类型的参数的值是从IOC容器中获取, 比如说 我们启动IOC容器后,就会在IOC容器中找类型未 Car.class 类型的组件public Boss(Car car) {this.car = car;}public Boss() {}public Car getCar() {return car;}public void setCar(Car car) {this.car = car;}@Overridepublic String toString() {return "Boss{" +"car=" + car +'}';}
}

3.配置类

package com.jsxs.config;import com.jsxs.mapper.BookMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;/*** @Author Jsxs* @Date 2023/8/17 11:14* @PackageName:com.jsxs.config* @ClassName: MainConfigOfAutowried* @Description: TODO**/@Configuration
@ComponentScan(value = "com.jsxs") //⭐⭐扫描
public class MainConfigOfAutowried {@Primary@Bean("book2")public BookMapper bookMapper() {BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}}

4.测试

package com.jsxs.Test;import com.jsxs.bean.Boss;
import com.jsxs.bean.Car;
import com.jsxs.mapper.BookMapper;
import com.jsxs.config.MainConfigOfAutowried;
import com.jsxs.service.BookService;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 11:23* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Autowried* @Description: TODO* @Version 1.0*/
public class IOCTest_Autowried {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfAutowried.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}Boss bean = applicationContext.getBean(Boss.class);Car bean1 = applicationContext.getBean(Car.class);System.out.println(bean);System.out.println(bean1);}
}

在这里插入图片描述

(3).@Bean + 方法参数

@Bean+方法参数 ,这里的参数默认是从IOC容器中获取的。默认不写@Autowried 也会自动装配

    @Primary@Bean("book2")public BookMapper bookMapper(Car car) {  //⭐ 这个Car 也是从IOC容器中获取的BookMapper bookMapper = new BookMapper();bookMapper.setLabel("2");return bookMapper;}

4.自定义组件使用Spring容器底层的一些组件

(1).xxxAware

自定义组件实现xxxAware: 在创建对象的时候,会调用接口规定的方法注入相关组件。Aware

在这里插入图片描述

在这里插入图片描述

5.@Profile 切换多个应用场景

(1). 环境搭建

1.依赖

        <dependency><groupId>com.mchange</groupId><artifactId>c3p0</artifactId><version>0.9.5.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.6</version></dependency>

2.配置类

package com.jsxs.config;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;import javax.sql.DataSource;
import java.beans.PropertyVetoException;/*** @Author Jsxs* @Date 2023/8/17 20:59* @PackageName:com.jsxs.config* @ClassName: MainConfigOfProfile* @Description: TODO   Profile:*                          Spring为我们提供的可以根据当前环境,动态的激活和切换一系列bean的功能*                          (1).开发环境、测试环境、生产环境** @Version 1.0*/
@PropertySource("classpath:/db.properties")  // 1. 因为要读取外部的文件,所以我们需要指定外部的文件的位置
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware {  // 2.实现EmbeddedValueResolverAware解析器接口,这个接口主要是能够解析 ${} 和 #{}@Value("${db.user}")  // 3.  获取外部的文件,并赋值private String user;@Value("${db.password}")private String password;@Value("${db.driverClass}")private String Driver;// 4. 进行依赖注入的操作private StringValueResolver stringValueResolver;@Bean("DataSourceTest")public DataSource dataSourceTest() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/demo1");dataSource.setDriverClass(Driver);return dataSource;}@Bean("DataSourceDev")public DataSource dataSourceDev() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/library");dataSource.setDriverClass(Driver);return dataSource;}@Bean("DataSourceProd")public DataSource dataSourceProd() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ckqn");// 5. 获取解析到的值String value = stringValueResolver.resolveStringValue("${db.driverClass}");dataSource.setDriverClass(value);return dataSource;}// 6. 依赖注入@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {this.stringValueResolver=resolver;}
}

3.外部资源文件

db.user=root
db.password=121788
db.driverClass=com.mysql.jdbc.Driver

4.测试

package com.jsxs.Test;import com.jsxs.config.MainConfigOfProfile;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 21:31* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Profile* @Description: TODO* @Version 1.0*/
public class IOCTest_Profile {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfProfile.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
}

在这里插入图片描述

(2).根据环境注册bean (环境切换)

如何切换环境呢?

/*** 切换环境的方式:*  1、使用命令行动态参数:在虚拟机参数位置加载-Dspring.profiles.active=test(test是测试的环境标识)*  2、代码的方式激活某种环境*/
package com.jsxs.config;import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.EmbeddedValueResolverAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.context.annotation.PropertySource;
import org.springframework.util.StringValueResolver;import javax.sql.DataSource;
import java.beans.PropertyVetoException;/*** @Author Jsxs* @Date 2023/8/17 20:59* @PackageName:com.jsxs.config* @ClassName: MainConfigOfProfile* @Description: TODO   @Profile:指定组件在哪个环境的情况下才能被注册到容器中。 @Bean: 任何环境下都可以被注册到容器中*                      Spring为我们提供的可以根据当前环境,动态的激活和切换一系列bean的功能*                      (1).开发环境、测试环境、生产环境*                      (2).加了环境标识的bean,只有这个环境被激活的时候才能注册* @Version 1.0*/
@PropertySource("classpath:/db.properties")  // 1. 因为要读取外部的文件,所以我们需要指定外部的文件的位置 ⭐
@Configuration
public class MainConfigOfProfile implements EmbeddedValueResolverAware {  // 2.实现EmbeddedValueResolverAware解析器接口,这个接口主要是能够解析 ${} 和 #{}@Value("${db.user}")  // 3.  获取外部的文件,并赋值private String user;@Value("${db.password}")private String password;@Value("${db.driverClass}")private String Driver;// 4. 进行依赖注入的操作private StringValueResolver stringValueResolver;//    @Profile("default")  假如我们写的是default,那么就会使用注解下方的数据源@Profile("test") ⭐⭐@Bean("DataSourceTest")public DataSource dataSourceTest() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/demo1");dataSource.setDriverClass(Driver);return dataSource;}@Profile("dev")⭐⭐⭐@Bean("DataSourceDev")public DataSource dataSourceDev() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/library");dataSource.setDriverClass(Driver);return dataSource;}@Profile("prod")⭐⭐⭐@Bean("DataSourceProd")public DataSource dataSourceProd() throws PropertyVetoException {ComboPooledDataSource dataSource = new ComboPooledDataSource();dataSource.setUser(user);dataSource.setPassword(password);dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/ckqn");// 5. 获取解析到的值String value = stringValueResolver.resolveStringValue("${db.driverClass}");dataSource.setDriverClass(value);return dataSource;}// 6. 依赖注入@Overridepublic void setEmbeddedValueResolver(StringValueResolver resolver) {this.stringValueResolver = resolver;}
}
package com.jsxs.Test;import com.jsxs.config.MainConfigOfProfile;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;/*** @Author Jsxs* @Date 2023/8/17 21:31* @PackageName:com.jsxs.Test* @ClassName: IOCTest_Profile* @Description: TODO* @Version 1.0*/
public class IOCTest_Profile {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();// 1.指定环境 ⭐applicationContext.getEnvironment().setActiveProfiles("test");// 2.指定配置类 ⭐⭐applicationContext.register(MainConfigOfProfile.class);// 3.刷新容器  ⭐⭐⭐applicationContext.refresh();// 4.输出所有的组件for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}}
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/42303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

QT多屏显示程序

多屏显示的原理其实很好理解&#xff0c;就拿横向扩展来说&#xff1a; 计算机把桌面的 宽度扩展成了 w1&#xff08;屏幕1的宽度&#xff09; w2(屏幕2的宽度) 。 当一个窗口的起始横坐标 > w1&#xff0c;则 他就被显示在第二个屏幕上了。 drm设备可以多用户同时打开&am…

Spring MVC 简介

目录 1. 什么是MVC2. 什么是SpringMVC 1. 什么是MVC MVC是一种常用的软件架构模式。可以看作是一种设计模式&#xff0c;也可以看作是一种软件框架。经典MVC模式中&#xff0c;M是指模型&#xff0c;V是视图&#xff0c;C则是控制器&#xff0c;使用MVC的目的是将M和V的实现代…

golang中使用chan控制协程并发简单事例

func main() {processNum : 5ch : make(chan struct{}, processNum)for true {ch <- struct{}{}go func() {defer func() {<-ch}()fmt.Println("我是协程", time.Now().UnixNano())time.Sleep(time.Second * 5)}()} } 可以看到&#xff0c;这里每5s会执行一次带…

Linux15 消息队列 线程

目录 1、进程间通信IPC&#xff1a; 2、多线程 3、向消息队列中写入数据 4、从消息队列中读取数据 5、多线程&#xff1a; 6、将多线程的数据返回给主…

数据库索引优化策略与性能提升实践

文章目录 什么是数据库索引&#xff1f;为什么需要数据库索引优化&#xff1f;数据库索引优化策略实践案例&#xff1a;索引优化带来的性能提升索引优化规则1. 前导模糊查询不适用索引2. 使用IN优于UNION和OR3. 负向条件查询不适用索引4. 联合索引最左前缀原则5. 范围条件查询右…

【Mysql】MVCC版本机制的多并发

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

PostgreSQL空值的判断

PostgreSQL空值的判断 空值判断非空判断总结 空值判断 -- 查询为空的 is null,sql简写isnull select * from employees where manager_id isnull;select * from employees where manager_id is null;非空判断 -- 查询不为空的 is not null;sql简写notnull select * from empl…

Java【数据结构】二分查找

&#x1f31e; 题目&#xff1a; &#x1f30f;在有序数组A中&#xff0c;查找目标值target &#x1f30f;如果找到返回索引 &#x1f30f;如果找不到返回-1 算法描述解释前提给定一个内含n个元素的有序数组A&#xff0c;满足A0<A1<A2<<An-1,一个待查值target1设…

mysql 8.0安装

操作系统&#xff1a;22.04.1-Ubuntu apt 安装命令 sudo apt install mysql-client-core-8.0 sudo apt install mysql-server-8.0终端输入 mysql 可以直接免密登录 如果此时提示需要密码&#xff0c;则可以进入配置文件&#xff0c;设置免密登录 sudo vim /etc/mysql/mysq…

【探索Linux】—— 强大的命令行工具 P.5(yum工具、git 命令行提交代码)

阅读导航 前言一、软件包管理器 yum1.yum的概念yum的基本指令使用例子 二、git 命令行提交代码总结温馨提示 前言 前面我们讲了C语言的基础知识&#xff0c;也了解了一些数据结构&#xff0c;并且讲了有关C的一些知识&#xff0c;也学习了一些Linux的基本操作&#xff0c;也了…

20W IP网络吸顶喇叭 POE供电吸顶喇叭

SV-29852T 20W IP网络吸顶喇叭产品简介 产品用途&#xff1a; ◆室内豪华型吸顶喇叭一体化网络音频解码扬声器&#xff0c;用于广播分区音频解码、声音还原作用 ◆应用场地如火车站、地铁、教堂、工厂、仓库、公园停车场等&#xff1b;室内使用效果均佳。 产品特点&#xff…

pytorch_lightning报错 You requested gpu: [1],But your machine only has: [0]

pytorch_lightning报错 You requested gpu: [1]&#xff0c;But your machine only has: [0] 问题及分析 报错图片如下&#xff1a; 分析 gpu:[1]指代的gpu的标号&#xff0c;如果笔记本中只包含一个GPU&#xff0c;一般序号为[0].所以无法找到程序指定的GPU。 解决方法 …

编程语言学习笔记-架构师和工程师的区别,PHP架构师之路

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;CSDN博客专家&#xff0c;阿里云社区专家博主&#xff0c;2023年6月CSDN上海赛道top4。 &#x1f3c6;数年电商行业从业经验&#xff0c;历任核心研发工程师&#xff0c;项目技术负责…

Egg.js构建一个stream流式接口服务

经常需要用到 stream 流式接口服务,比如&#xff1a;大文件下载、日志实时输出等等。本文将介绍如何使用Egg.js构建一个 stream 流式接口服务。 一、准备工作 目录结构&#xff1a; app//controllerindex.jstest.txttest.shindex.js 控制器test.txt 测试文件&#xff0c;最好…

5G+AI数字化智能工厂建设解决方案PPT

导读&#xff1a;原文《5GAI数字化智能工厂建设解决方案》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。数字化智能工厂定义 智能基础架构协同框架 - 端、边、云、网…

激光雷达 01 线数

一、线数 对于 360 旋转式和一维转镜式架构的激光雷达来说&#xff0c;有几组激光收发模块&#xff0c;垂直方向上就有几条线&#xff0c;被称为线数。这种情况下&#xff0c;线数就等同于激光雷达内部激光器的数量[参考]。 通俗来讲&#xff0c;线数越高&#xff0c;激光器的…

npm run xxx 的时候发生了什么?(以npm run dev举例说明)

文章目录 一、去package.json寻找scripts对应的命令二、去node_modules寻找vue-cli-service三、从package-lock.json获取.bin的软链接1. bin目录下的那些软连接存在于项目最外层的package-lock.json文件中。2.vue-cli-service文件的作用3.npm install 的作用 总结 一、去packag…

Google API实战与操作

Google api实战与操作 一. Google API 权限配置二. 操作API2.1 引入依赖2.2 导入代码 Google官网 实现一套用java程序控制GoogleAPI实现自动生成监控日报等功能,具体能操作Gsheet及document 一. Google API 权限配置 打开上面官网,新建项目 启用API 搜索sheet及document …

【山河送书第七期】:《强化学习:原理与Python实战》揭秘大模型核心技术RLHF!

《强化学习&#xff1a;原理与Python实战》揭秘大模型核心技术RLHF&#xff01; 一图书简介二RLHF是什么&#xff1f;三RLHF适用于哪些任务&#xff1f;四RLHF和其他构造奖励模型的方法相比有何优劣&#xff1f;五什么样的人类反馈才是好反馈&#xff1f;六如何减小人类反馈带来…

web前端开发基础入门html5+css3+js学习笔记(一)

目录 1.第一个前端程序2.前端工具的选择与安装3.VSCode开发者工具快捷键4.HTML5简介与基础骨架4.1 HTML5的DOCTYPE声明4.2 HTML5基本骨架4.2.1 html标签4.2.2 head标签4.2.3 body标签4.2.4 title标签4.2.5 meta标签 5.标签之标题5.1 快捷键5.1 标题标签位置摆放 6.标签之段落、…