Spring注解驱动开发笔记-IoC篇

该笔记是在本人学习Spring注解开发的时候记录的,参考了尚硅谷的Spring注解驱动开发视频,现在发出来供自己和大家参考

IoC篇点这里

AOP篇点这里

声明式事务篇点这里

扩展原理篇点这里

Spring容器的创建篇点这里

文章目录

Spring注解驱动开发-IoC篇

Bean的注册:

一、组件注册—使用@Configuration、@Bean给容器中注册组件

1.导入Spring所需依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.wxr</groupId>
    <artifactId>spring-annotation</artifactId>
    <version>1.0-SNAPSHOT</version>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>4.3.12.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/javax.inject/javax.inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/c3p0/c3p0 -->
        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency> 
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.44</version>
        </dependency>
    </dependencies>
</project>

2.创建配置类(MyConfig)

package com.wxr.config;
import com.wxr.bean.Person;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**配置类==beans.xml
 * @author FatterShadystart
 * @create 2022-02-12 17:37
 */
//告诉spring这是一个配置类
@Configuration
public class MyConfig {
    //给容器中注册一个Bean,类型为返回值的类型,id是默认方法名作为的id
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }

}

3.在测试类里面获取注册的Bean对象以及获取所有Bean对象的名字

public class MainTest {
    public static void main(String[] args){
        //配置文件的方式
//        ClassPathXmlApplicationContext ioc = new ClassPathXmlApplicationContext("classpath:beans.xml");
//        Person person = ioc.getBean("person", Person.class);
//        System.out.println(person);
        //配置类
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig.class);
        Person person = ioc.getBean("person", Person.class);
        System.out.println(person);
        String[] beanNamesForType = ioc.getBeanNamesForType(Person.class);
        for (String name : beanNamesForType) {
            System.out.println(name);
        }
    }
}

4.输出结果

在这里插入图片描述

二、组件注册—@ComponentScan自动扫描组件和指定扫描规则

1.和xml配置一样context:component-scan,只要标注了@Controller、@Service、@Repository、@Component,都会被这个注解扫描到(在MyConfig配置类中写)

1.1excludeFilters
/**配置类==beans.xml
 * @author FatterShadystart
 * @create 2022-02-12 17:37
 */
//告诉spring这是一个配置类
@Configuration
//@ComponentScan,value:指定要扫描的包
//excludeFilters=Filter[]:指定扫描的时候按照什么规则排除组件
//includeFilters=Filter[]:指定扫描的时候只需要包含符合规则的组件
@ComponentScan(value = "com.wxr",excludeFilters = {
        //不扫描Controller注解
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})
})
public class MyConfig {
    //给容器中注册一个Bean,类型为返回值的类型,id是默认方法名作为的id
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }

}

1.2includeFilters
/**配置类==beans.xml
 * @author FatterShadystart
 * @create 2022-02-12 17:37
 */
//告诉spring这是一个配置类
@Configuration
//@ComponentScan,value:指定要扫描的包
//excludeFilters=Filter[]:指定扫描的时候按照什么规则排除组件
//includeFilters=Filter[]:指定扫描的时候只需要包含符合规则的组件
@ComponentScan(value = "com.wxr",includeFilters = {
        //不扫描Controller和Service注解
        @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class})},
        //使用includeFilters的时候要禁用掉默认的过滤规则
        useDefaultFilters = false
)
public class MyConfig {
    //给容器中注册一个Bean,类型为返回值的类型,id是默认方法名作为的id
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }
}
1.3自定义TypeFilter指定过滤规则
1.3.1配置类的写法
//告诉spring这是一个配置类
@Configuration
//@ComponentScan,value:指定要扫描的包
//excludeFilters=Filter[]:指定扫描的时候按照什么规则排除组件
//includeFilters=Filter[]:指定扫描的时候只需要包含符合规则的组件
@ComponentScan(value = "com.wxr",includeFilters = {
        @ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
        },useDefaultFilters = false
)
public class MyConfig {
    //给容器中注册一个Bean,类型为返回值的类型,id是默认方法名作为的id
    @Bean
    public Person person(){
        return new Person("lisi",18);
    }

}

1.3.2要实现自定义指定过滤规则,需要新建一个类然后实现TypeFilter,在match方法里面自定义过滤规则
public class MyTypeFilter implements TypeFilter {
    /**
     * @param metadataReader        读取到当前正在扫描的类的信息
     * @param metadataReaderFactory 可以获取到其他任何类的信息
     * @return
     * @throws IOException
     */
    @Override
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //获取当前正在扫描的类的类信息
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //获取当前扫描类的类名
        String className = classMetadata.getClassName();
        //如果类名包含"er"那么就扫描成功
        if (className.contains("er")) {
            return true;
        }
        return false;
    }
}

2.在测试类里面获取所有的Bean对象的名字

 	@Test
    public void test01(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig.class);
        String[] definitionNames = ioc.getBeanDefinitionNames();
        for (String name : definitionNames) {
            System.out.println(name);
        }
    }

3.输出结果

1.1的结果

在这里插入图片描述

1.2的结果

在这里插入图片描述

1.3的结果

在这里插入图片描述

三、组件注册—@Scope设置组件作用域和@Lazy实现Bean懒加载

1.创建配置类MyConfig2

1.1单实例(默认值)
@Configuration
public class MyConfig2 {
    @Bean("person")
    /**
     * prototype: 多实例的:ioc容器启动并不会去调用方法创建对象放到ioc容器中,而是每次获取的时候才会调用方法创建对象。
     * singleton:单实例的(默认值):ioc容器启动的时候会调用方法创建对象放到ioc容器中,以后每次获取都直接从容器中拿。
     */
    @Scope("singleton")
    public Person person(){
        System.out.println("给容器中添加....person对象");
        return new Person("zhangsan",25);
    }
}
1.2多实例
@Configuration
public class MyConfig2 {
    @Bean("person")
    /**
     * prototype: 多实例的:ioc容器启动并不会去调用方法创建对象放到ioc容器中,而是每次获取的时候才会调用方法创建对象。
     * singleton:单实例的(默认值):ioc容器启动的时候会调用方法创建对象放到ioc容器中,以后每次获取都直接从容器中拿。
     */
    @Scope("prototype")
    public Person person(){
        System.out.println("给容器中添加....person对象");
        return new Person("zhangsan",25);
    }
}
1.3单实例配合懒加载
@Configuration
public class MyConfig2 {

    @Bean("person")
    /**
     * prototype: 多实例的:ioc容器启动并不会去调用方法创建对象放到ioc容器中,而是每次获取的时候才会调用方法创建对象。
     * singleton:单实例的(默认值):ioc容器启动的时候会调用方法创建对象放到ioc容器中,以后每次获取都直接从容器中拿。
     * 懒加载:
     *      单实例bean:默认在容器启动的时候创建对象
     *      懒加载:容器启动不创建对象。第一次使用(获取)Bean的时候创建对象,并且初始化。
     */
    @Lazy
    @Scope("singleton")
    public Person person(){
        System.out.println("给容器中添加....person对象");
        return new Person("zhangsan",25);
    }
}

2.在测试类里面测试Bean对象的获取

@Test
public void test02(){
    AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig2.class);
    System.out.println("ioc容器创建完成。。。。");
    Person person = ioc.getBean("person", Person.class);
    Person person1 = ioc.getBean("person", Person.class);
    System.out.println(person==person1);
 }

3.输出结果

1.1的结果(单实例默认在ioc容器启动的时候就创建对象放到ioc容器中,每次获取的时候直接从容器中拿)

在这里插入图片描述

1.2的结果(ioc容器启动并不会去调用方法创建对象放到ioc容器中,而是每次获取的时候才会调用方法创建对象。)

在这里插入图片描述

1.3的结果(添加@Lazy懒加载注解后,ioc容器启动时不创建对象。第一次使用(获取)Bean的时候创建对象,并且初始化。)

在这里插入图片描述

四、组件注册—@Conditional 按条件注册Bean

1.创建配置类MyConfig2

@Configuration
//@Conditional加在类上的话,要满足当前条件,这个类中配置的所有bean注册才会生效
//@Conditional({WindowsCondition.class})
public class MyConfig2 {

    /**
     *@Conditional
     * 如果是windows系统,就给容器注册Windows
     * 如果是linux系统,就给容器注册Linux
     *
     * @return
     */
    @Conditional({LinuxCondition.class})
    @Bean("Linux")
    public Person person02(){
        return new Person("Linux liuns",21);
    }

    @Conditional({WindowsCondition.class})
    @Bean("Windows")
    public Person person01(){
        return new Person("Windows Bill",20);
    }
}

2.创建条件类,实现Condition接口

/**判断是否是Linux系统
 * @author FatterShadystart
 * @create 2022-02-13 14:57
 */
public class LinuxCondition implements Condition {
    /**
    
     * @param context 判断条件能使用的上下文环境
     * @param metadata 当前标注了condition注解的注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取ioc的BeanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        String property = environment.getProperty("os.name");
        if(property.contains("linux")){
            return true;
        }
        return false;
    }
}
/**判断是否是Windows系统
 * @author FatterShadystart
 * @create 2022-02-13 14:57
 */
public class WindowsCondition implements Condition{
    /**
     * @param context 判断条件能使用的上下文环境
     * @param metadata 当前标注了condition注解的注释信息
     * @return
     */
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        //获取ioc的BeanFactory
        ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
        //获取类加载器
        ClassLoader classLoader = context.getClassLoader();
        //获取当前环境信息
        Environment environment = context.getEnvironment();
        //获取bean定义的注册类
        BeanDefinitionRegistry registry = context.getRegistry();

        String property = environment.getProperty("os.name");
        if(property.contains("Windows")){
            return true;
        }
        return false;
    }
}

3.编写测试类,输出注册的Bean对象名和Bean对象

@Test
public void test03(){
    AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig2.class);
    String[] beanDefinitionNames = ioc.getBeanNamesForType(Person.class);
    for (String name : beanDefinitionNames) {
        System.out.println(name);
    }
    System.out.println("*********************************");
    Map<String, Person> persons = ioc.getBeansOfType(Person.class);
    System.out.println(persons);

}

4.输出结果

在这里插入图片描述

五、组件注册方法总结(@Import和FactoryBean的使用)

1.给容器中注册组件的方法:

1.1包扫描(ComponentScan)+组件标注注解(@Controller/@Service/@Repository/@Component)

1.2@Bean:导入第三方包未写组件标注注解的组件

1.3@Import:根据无参构造快速给容器中导入一个组件

​			1.3.1@Import(要导入到容器中的组件),容器就会自动注册这个组件,id是默认的全类名

​			1.3.2 ImportSelector:返回需要导入的组件的全类名数组

​			1.3.3 ImportBeanDefinitionRegistrar:手动注册bean到容器中


1.4使用Spring提供的FactoryBean(工厂Bean):
​	默认获取到的是工厂bean调用getObject创建的对象。如果要获取工厂本身就在getBean()的id前面加一个“&”标识


2.创建配置类MyConfig3

1.3.1的实现(只需要创建MyConfig3配置类)
@Configuration
//@Import导入组件,id默认是组件的全类名
@Import({Color.class, Red.class})
public class MyConfig3 {
}
1.3.2的实现(创建MyConfig3配置类后,再创建MyImportSelector实现ImportSelector接口)
@Configuration
//@Import导入组件,MyImportSelector是自定义返回需要导入的组件的全类名数组
@Import({MyImportSelector.class})
public class MyConfig3 {
}
public class MyImportSelector implements ImportSelector {
    /**
     *
     * @param importingClassMetadata 当前标注Import注解的类的所有注解信息
     * @return 导入到容器中组件的全类名
     */
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.wxr.bean.Blue","com.wxr.bean.Yellow"};
    }
}

1.3.3的实现(创建MyConfig3配置类后,再创建MyImportBeanDefinitionRegistrar实现ImportBeanDefinitionRegistrar接口)
@Configuration
//@Import导入组件,MyImportBeanDefinitionRegistrar自定义手动注册bean到容器中
@Import({Blue.class,Red.class,MyImportBeanDefinitionRegistrar.class})
public class MyConfig3 {
}
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {


    /**
     *
     * @param importingClassMetadata 当前类的注解信息
     * @param registry BeanDefinition注册类:把所有需要添加到容器中的Bean(调用BeanDefinitionRegistry.registerBeanDefinition手动注册进来)
     */
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //全类名
        boolean definition1 = registry.containsBeanDefinition("com.wxr.bean.Red");
        boolean definition2 = registry.containsBeanDefinition("com.wxr.bean.Blue");
        if(definition1&&definition2){
            //指定Bean定义信息(Bean的类型,Bean的作用域...)
            RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(RainBow.class);
            //注册一个Bean,指定bean名
            registry.registerBeanDefinition("rainBow", rootBeanDefinition);
        }
    }
}
1.4的实现(创建MyConfig3配置类后,再创建ColorFactoryBean实现FactoryBean接口)
@Configuration
public class MyConfig3 {
    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
}
/**
 * 创建一个Spring定义的工厂Bean
 */
public class ColorFactoryBean implements FactoryBean<Color>{
    /**
     * @return 返回一个Color对象这个对象会添加到容器中
     * @throws Exception
     */
    @Override
    public Color getObject() throws Exception {
        return new Color();
    }
    
    /**
     * @return 返回对象的类型
     */
    @Override
    public Class<?> getObjectType() {
        return Color.class;
    }

    /**
     * @return  true:单实例  false:多实例
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

3.在测试类里面获取所有的Bean对象的名字

1.3的测试类
    @Test
    public void test04(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig3.class);
        String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
    }

1.4的测试类
 @Test
    public void test05(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfig3.class);
        String[] beanDefinitionNames = ioc.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) {
            System.out.println(name);
        }
        //工厂Bean获取的是调用getObject创建的对象
        Object colorFactoryBean = ioc.getBean("colorFactoryBean");
        System.out.println("bean的类型:"+colorFactoryBean.getClass());
        //如果要获取工厂Bean就在前面加上&前缀
        Object colorFactoryBean1 = ioc.getBean("&colorFactoryBean");
        System.out.println("beanFactory的类型:"+colorFactoryBean1.getClass());
    }


4.输出结果

1.3.1的结果

在这里插入图片描述

1.3.2的结果

在这里插入图片描述

1.3.3的结果

在这里插入图片描述

1.4的结果

在这里插入图片描述

二、Bean的生命周期

一、指定初始化和销毁方法—@Bean

1.bean的生命周期

bean创建—>初始化---->销毁的过程

bean的生命周期是通过容器进行管理:我们可以自定义初始化和销毁方法,当容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

2.指定初始化和销毁方法—基于XML配置方式

    <bean id="person" class="com.wxr.bean.Person" scope="prototype" init-method="" destroy-method="">

3.指定初始化和销毁方法—基于注解配置方式

3.1通过@Bean的initMethod、destroyMethod进行调用实现
3.1.1创建配置类MainConfigOfLifeCycle
@Configuration
public class MainConfigOfLifeCycle {
    //指定初始化和销毁方法
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car car() {
        return new Car();
    }
}

3.1.2创建Car类,包含构造器,init,destroy方法
public class Car {
    public Car() {
        System.out.println("car的构造器.........");
    }
    public void init() {
        System.out.println("car的初始化方法........");
    }
    public void destroy() {
        System.out.println("car的销毁方法.........");
    }
}
3.1.3测试代码
	/**
     * @Scope("singleton")
     */
	@Test
    public void test01(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("ioc容器创建完成");
        ioc.close();
    }
	/**
     * @Scope("prototype")
     */
	@Test
   public void test02(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("ioc容器创建完成");
        Object car = ioc.getBean("car");
        ioc.close();
 }
3.1.4输出结果

test01:

在这里插入图片描述
test02:
在这里插入图片描述

说明:

1.构造器(对象的创建):

​ 单实例:在容器启动的时候创建对象

​ 多实例:在每次获取的时候创建对象

2.初始化:在对象创建完成(实例化),并赋值以后(初始化),调用初始化方法(initMethod)

3.销毁:

​ 单实例:容器关闭的时候

​ 多实例:容器不会管理这个bean,容器不会调用销毁方法

3.2通过Bean实现InitializingBean(定义初始化逻辑),DisposableBean(定义销毁逻辑) 接口实现
3.2.1创建配置类MainConfigOfLifeCycle
@Configuration
@ComponentScan("com.wxr")
public class MainConfigOfLifeCycle {
}
3.2.2创建Computer类,包含构造器,实现InitializingBean,DisposableBean接口
@Component
public class Computer implements InitializingBean,DisposableBean {
    public Computer() {
        System.out.println("Computer的构造器.........");
    }

    /**
     * 和自己写的init方法一样
     *
     * @throws Exception
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Computer的afterPropertiesSet(初始化方法).........");
    }
    /**
     * 和自己写的destroy方法一样
     *
     * @throws Exception
     */
    @Override
    public void destroy() throws Exception {
        System.out.println("Computer的destroy(销毁方法).........");
    }
}

3.2.3测试代码

@Test
public void test03(){
    AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    System.out.println("ioc容器创建完成");
    ioc.close();
}

3.2.4输出结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VWGT8nFu-1646491451180)(C:\Users\MateBook\Desktop\IDE、数据库系统等工具\API文档\SSM\Spring注解驱动开发\image-20220213212332471.png)]

3.3通过JSR250的@PostConstruct(在bean创建完成并且复制完成的时候执行),@PreDestroy(在容器销毁bean之前通知用户进行清理工作)实现
3.3.1创建配置类MainConfigOfLifeCycle
@Configuration
@ComponentScan("com.wxr")
public class MainConfigOfLifeCycle {
}
3.3.2创建Computer类,包含构造器
@Component
public class Student {
    public Student() {
        System.out.println("Student的构造器.........");
    }

    //对象创建并赋值后调用
    @PostConstruct
    public void init() {
        System.out.println("Student的@PostConstruct(init方法).........");
    }

    //容器移除对象之前
    @PreDestroy
    public void destroy() {
        System.out.println("Student的@PreDestroy(destroy方法)..........");
    }
}

3.3.3测试代码
@Test
public void test03(){
    AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
    System.out.println("ioc容器创建完成");
    ioc.close();
}
3.3.4输出结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-43P0V87D-1646491451181)(C:\Users\MateBook\Desktop\IDE、数据库系统等工具\API文档\SSM\Spring注解驱动开发\image-20220213214336799.png)]

3.4通过自定义 BeanPostProcessor(bean的后置处理器)接口实现
3.4.1创建一个Car对象
@Component
public class Car {

    public Car() {
        System.out.println("car的构造器.........");
    }
    public void init() {
        System.out.println("car的初始化方法........");
    }
    public void destroy() {
        System.out.println("car的销毁方法.........");
    }
}
3.4.2创建配置类MainConfigOfLifeCycle
@Configuration
//导入自定义后置处理器
@Import(MyBeanPostProcessor.class)
public class MainConfigOfLifeCycle {
		//创建一个Car对象实现init,和destroy方法
        @Bean(initMethod = "init",destroyMethod = "destroy")
        public Car car(){
            return new Car();
        }

}

3.4.3创建MyBeanPostProcessor类,实现BeanPostProcessor接口
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
  
    /**
     * @param bean 刚创建的bean实例对象
     * @param beanName 刚创建的bean实例对象名字
     * @return 返回源对象或者是包装好的对象
     * @throws BeansException
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"-->"+bean);
        return bean;
    }
    /**
     * @param bean 刚创建的bean实例对象
     * @param beanName 刚创建的bean实例对象名字
     * @return 返回源对象或者是包装好的对象
     * @throws BeansException
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"-->"+bean);
        return bean;
    }
}


3.4.4测试代码
@Test
   public void test03(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("ioc容器创建完成");
        ioc.close();
 }
3.4.5输出结果

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0pjKz51C-1646491451181)(C:\Users\MateBook\Desktop\IDE、数据库系统等工具\API文档\SSM\Spring注解驱动开发\image-20220219002326026.png)]

说明:后置处理器执行位置

构造器(对象的创建)

BeanPostProcessor.postProcessBeforeInitialization :在bean初始化之前工作

初始化:在对象创建完成(实例化),并赋值以后(初始化),调用初始化方法(initMethod)

BeanPostProcessor.postProcessAfterInitialization:在bean初始化之后工作

销毁

二、属性赋值—@Value的使用

1.创建配置类MyConfigOfPropertyValues

//使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中
@PropertySource(value = {"classpath:Person.properties"})
@Configuration
public class MyConfigOfPropertyValues {
    @Bean
    public Person person(){
        return new Person();
    }
}

2.在要赋值的bean的属性中加入@Value

public class Person {
    /**
     * @Value 可以写的值:
     *                   1.基本数值
     *                   2.SpEL:#{}
     *                   3.取出配置文件中的值:${}
     *
     */
    @Value("张三")
    private String name;
    @Value("#{20-2}")
    private Integer age;
    @Value("${person.nickname}")
    private String nickName;
    public Person() {
    }
    public Person(String name, Integer age, String nickName) {
        this.name = name;
        this.age = age;
        this.nickName = nickName;
    }
    public Person(String name, Integer age) {
        this.name = name;
        this.age = age;

    } 
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", nickName='" + nickName + '\'' +
                '}';
    }
    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;
    }
}

在自定义配置文件Person.properties中写值
person.nickname=\u5C0F\u5f20\u4E09

3.测试代码

  @Test
    public void test04(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfigOfPropertyValues.class);
        Person person = ioc.getBean("person", Person.class);
        System.out.println(person);
    }

4.输出结果

在这里插入图片描述

三、自动装配—@Autowired、@Qualifier的使用

1.自动装配概念

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

AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能

2.使用自动装配

2.1@Autowired、@Qualifier的使用
2.1.1创建配置类MyConfigAutowired
2.1.1.1创建配置类MyConfigAutowired(没有再次获得相同类型的组件)
@Configuration
@ComponentScan(value = {"com.wxr.service","com.wxr.dao","com.wxr.controller"})
public class MyConfigAutowired {
 
}
2.1.1.2创建配置类MyConfigAutowired(获得相同类型的组件)
@Configuration
@ComponentScan(value = {"com.wxr.service","com.wxr.dao","com.wxr.controller"})
public class MyConfigAutowired {
    @Bean("bookDao2")
    public BookDao bookDao() {
        BookDao bookDao2 = new BookDao();
        bookDao2.setLabel("2");
        return  bookDao2;
    }
}
2.1.2创建BookController、BookService、BookDao类
2.1.2.1创建BookController、BookService、BookDao类(没有再次获得相同类型的组件)
@Controller
public class  BookController {
    @Autowired
    private BookService bookService;
}


@Service
public class BookService {
    @Autowired
    private BookDao bookDao;
    
    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

@Repository
public class BookDao {
    private String label="1";

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    @Override
    public String toString() {
        return "BookDao{" +
                "label='" + label + '\'' +
                '}';
    }
}

2.1.2.2创建BookController、BookService、BookDao类(获得相同类型的组件)
@Controller
public class  BookController {
    @Autowired
    private BookService bookService;
}

@Service
public class BookService {
    @Autowired 
    @Qualifier("bookDao2")
    private BookDao bookDao;
    @Override
    public String toString() {
        return "BookService{" +
                "bookDao=" + bookDao +
                '}';
    }
}

@Repository
public class BookDao {
    private String label="1";

    public String getLabel() {
        return label;
    }

    public void setLabel(String label) {
        this.label = label;
    }

    @Override
    public String toString() {
        return "BookDao{" +
                "label='" + label + '\'' +
                '}';
    }
}

2.1.3测试代码
      /**
     * 自动注入:
     			1.默认优先按照 类型 去容器中找对应的组件:相当于ioc.getBean(BookDao.class);找到就赋值
     			2.如果找到 多个相同类型 的组件,再将属性的名称作为组件的id去容器中查找:相当于ioc.getBean(“bookDao”)
     			  一般来说,如果找到多个相同类型的组件后,我们都要搭配着@Qualifier进行使用
     			3.@Qualifier指定需要装配的组件id,而不是使用属性名
                        BookService{
                                    @Autowired
     								BookDao    bookDao
                                    
       @Autowired的使用位置:构造器(如果组件只有一个有参构造器,这个有参构造器的@Autowired可以省略)、参数、方法、属性
       
     */
@Test
    public void test01(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfigAutowired.class);
        BookService beanBookService = ioc.getBean(BookService.class);
        System.out.print("自动注入的dao:"+beanBookService);
        System.out.println();
        BookDao beanBookDao = ioc.getBean("bookDao",BookDao.class);
        System.out.println("主动获取的dao:"+beanBookDao);
        ioc.close();
    }
2.1.4输出结果

在这里插入图片描述

获得了多个相同类型的组件的时候并且使用了@Qualifier后:

在这里插入图片描述

四.自动装配—Aware注入Spring底层组件

1.创建配置类MyConfigAutowired

/**
 * 自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,...)
 * 需要自定义组件实现xxxAware:在创建对象的时候,会调用接口规定的方法注入相关组件把Spring底层的一些组件注入到自定义的组件当中
 * xxxAware:功能是被xxxProcessor实现的:
 *               ApplicationContextAware==>ApplicationContextAwareProcessor
 *
 * @author FatterShadystart
 * @create 2022-02-14 17:24
 */
@Configuration
@ComponentScan(value = {"com.wxr.bean"})
public class MyConfigAutowired {

}

2.创建自定义组件实现XXXAware的类Red

@Component
public class Red implements ApplicationContextAware,BeanNameAware,EmbeddedValueResolverAware {

    private ApplicationContext applicationContext;

    @Override
    public void setBeanName(String name) {
        System.out.println("当前bean的名字:"+name);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("传入的ioc容器:"+applicationContext);
        this.applicationContext=applicationContext;
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        String s = resolver.resolveStringValue("你好${os.name}");
        System.out.println("解析的字符串是:"+s);
    }
}

3.测试代码

   @Test
    public void test01(){
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext(MyConfigAutowired.class);
        ioc.close();
    }

4.输出结果

在这里插入图片描述

五、自动装配—@Profile根据环境注册bean

1.创建db.properties文件

db.user=root
db.password=wxr.1005
db.driverClass=com.mysql.jdbc.Driver

2.创建配置类MyConfigOfProfile

/**
 * 一、Profile:
 *        Spring为我们提供的可以根据当前环境,动态地激活和切换一系列组件的功能
 *环境:
 *     开发环境、测试环境、生产环境
 *数据源:
 * (/A库)(/B库)(/C库)
 *
 * 二、@Profile:  指定组件在哪个环境的情况下才能被注册到容器中,如果不指定,任何环境下都可以注册这个组件
 *              1.加了环境标识的bean,只有在这个环境被激活的时候才能注册到容器中
 *              2.写在配置类上,只有是指定环境的时候,整个配置类的环境才会生效
 *              3.没有标注环境标识的bean,在任何情况下都会加载
 *
 * @author FatterShadystart
 * @create 2022-02-15 23:23
 */
//使用@PropertySource读取外部配置文件中的k/v保存到运行的环境变量中
@PropertySource(value = {"classpath:dbconfig.properties"})
@Configuration
public class MyConfigOfProfile implements EmbeddedValueResolverAware{

    @Value("${db.user}")
    private String user;

    private StringValueResolver valueResolver;

    private String driverClass;

    @Profile("test")
    @Bean("testDatasource")
    public DataSource datasourceTest(@Value("${db.password}")String pwd) throws Exception {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setUser(user);
        cpds.setPassword(pwd);
        cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        cpds.setDriverClass(driverClass);
        return cpds;
    }

    @Profile("develop")
    @Bean("developDatasource")
    public DataSource datasourceDevelop(@Value("${db.password}")String pwd) throws Exception {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setUser(user);
        cpds.setPassword(pwd);
        cpds.setJdbcUrl("jdbc:mysql://localhost:3306/ssm_crud");
        cpds.setDriverClass(driverClass);
        return cpds;
    }
    @Profile("Produce")
    @Bean("ProduceDatasource")
    public DataSource datasourceProduce(@Value("${db.password}")String pwd) throws Exception {
        ComboPooledDataSource cpds = new ComboPooledDataSource();
        cpds.setUser(user);
        cpds.setPassword(pwd);
        cpds.setJdbcUrl("jdbc:mysql://localhost:3306/book");
        cpds.setDriverClass(driverClass);
        return cpds;
    }

    /**
     * 任何环境下 未标识@Profile
     * @return
     */
    @Bean
    public Color color(){
        return  new Color();
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver resolver) {
        this.valueResolver=resolver;
        driverClass=valueResolver.resolveStringValue("${db.driverClass}");
    }
}

3.测试代码(输出所有Bean对象的名字)

 @Test
    public void test01(){
        //创建IoC容器
        AnnotationConfigApplicationContext ioc = new AnnotationConfigApplicationContext();
        //设置需要激活的环境
        ioc.getEnvironment().setActiveProfiles("test","develop");
        //注册主配置类
        ioc.register(MyConfigOfProfile.class);
        //启动刷新容器
        ioc.refresh();
        String[] DataSourceForType = ioc.getBeanNamesForType(DataSource.class);
        for (String name : DataSourceForType) {
            System.out.println(name);
        }
        String[] ColorForType = ioc.getBeanNamesForType(Color.class);
        for (String name : ColorForType) {
            System.out.println(name);
        }
        ioc.close();
    }

4.输出结果

在这里插入图片描述

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring-IOCSpring框架的核心部分之一,它是一种设计模式,全称为Inversion of Control(控制反转)。它通过将对象的创建、依赖关系的管理和对象的生命周期交给Spring容器来实现,从而降低了组件之间的耦合度,提高了代码的可重用性和可维护性。Spring-IOC的实现主要依靠Spring容器,Spring容器是Spring框架的核心,它负责创建、管理和装配Bean对象,其Bean是Spring框架最基本的组件。 Spring-IOC的实现主要有两种方式:BeanFactory和ApplicationContext。其,BeanFactory是Spring-IOC的基本实现,而ApplicationContext是BeanFactory的子接口,提供了更多高级特性。ApplicationContext是Spring框架最常用的IOC容器,它除了提供BeanFactory的所有功能外,还提供了更多的企业级特性,例如AOP、事务管理、国际化、事件传播等。 下面是一个简单的Spring-IOC的例子,假设我们有一个UserService接口和一个UserServiceImpl实现类,我们可以通过Spring-IOC容器来创建和管理UserServiceImpl对象: 1.定义UserService接口和UserServiceImpl实现类 ```java public interface UserService { void addUser(User user); } @Service public class UserServiceImpl implements UserService { @Override public void addUser(User user) { // 添加用户的具体实现 } } ``` 2.在Spring配置文件配置UserService实例 ```xml <bean id="userService" class="com.example.service.UserServiceImpl"/> ``` 3.在代码获取UserService实例并使用 ```java ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("userService", UserService.class); User user = new User(); userService.addUser(user); ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值