等等我

【Spring-IOC】你需要掌握的注解版开发!

大家好,我是小菜,一个渴望在互联网行业做到蔡不菜的小菜。可柔可刚,点赞则柔,白嫖则刚!

死鬼~看完记得给我来个三连哦!

本文主要介绍 Spring 中IOC的注解开发
如有需要,可以参考
如有帮助,不忘 点赞

创作不易,白嫖无义!

前戏概要:

XML 配置注入类:

  • 创建一个需要注入的类
  • 创建一个Spring 配置文件
  • 然后通过 的方式注册

基于注解注入:

  • 编写一个Person类:
public class Person {
    private String name;
    private Integer age;
    //省略 get / set 方法
}
  • 编写一个配置类:
//配置类==配置文件
@Configuration  //告诉Spring这是一个配置类
public class MainConfig {
    //给容器中注册一个Bean;类型为返回值的类型,id默认是用方法名作为id
    //也可以通过@Bean(value)的方式指定ID
    @Bean("person")
    public Person person01(){
        return new Person("Cbuc"22);
    }
}
  • 编写一个测试类:
public void test01(){
    //可以注意到之前基于xml的时候是 new ClassPathXmlApplicationContext() ,现在基于注解是 new AnnotationConfigApplicationContext()
    AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
    Person person = (Person) applicationContext.getBean("person");
    System.out.println(person);
}

成功获取到注入的类:

步骤详解

1)包扫描

XML扫描方式:可以配置配置一些过滤条件

<context:component-scan base-package="cbuc.lie" use-default-filters="false"></context:component-scan>

注解扫描方式:(@ComponentScan

FilterType.CUSTOM的使用

1)定义一个TypeFilter的实现类MyTypeFilter

2)通过@Filter(type=FilterType.CUSTOM,classes={MyTypeFilter.class}在classes中引入即可

2)作用域

通过@Scope:调整作用域(默认是单实例的)

  • singleton:单实例的(默认值),IOC容器启动会调用方法创建对象放到 IOC 容器中。 以后每次获取就是直接从容器 map.get()中拿,
  • request:同一次请求创建一个实例
  • session:同一个session创建一个实例

3)懒加载

单实例bean:默认在容器启动的时候创建对象;

懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化;

4) 按条件注入(@Conditional({Condition})

  1. 编写 Condition 的实现类 WindowsCondition
  1. 根据条件注入Bean
  1. 我们除了可以把 @Conditional 注解放在方法上 , 还可以放在类上(优先级比方法上高)

5) 给容器中导入一个组件(@Import

给容器中注册组件:

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

  2. 在配置类在通过@Bean 注册

  3. @Import (快速给容器中导入一个组件)

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

  • 2)ImportSelector:返回需要导入的组件的全类名数组

    编写ImportSelector的实现类

    在@Import中声明

  • 3)ImportBeanDefinitionRegistrar:手动注册bean到容器中

    编写ImportBeanDefinitionRegistrar的实现类


    在@Import中声明

6)FactoryBean(工厂Bean)

1)默认获取到的是工厂bean调用getObject创建的对象

2)要获取工厂Bean本身,我们需要给id前面加一个&colorFactoryBean

  1. 编写FactoryBean的实现类:

  2. 在配置类中注册:

    @Bean
    public ColorFactoryBean colorFactoryBean(){
        return new ColorFactoryBean();
    }
  1. 注意点:

此时虽然注入的是colorFactoryBean,但是获取到的是Color


如果想要获取colorFactoryBean,就在id前面加一个&

7)生命周期

bean的生命周期:

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

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

1)指定初始化和销毁方法;

  • 通过@Bean指定init-methoddestroy-method

我们创建一个Car类,里面自定义初始化和销毁方法:

public class Car {
    public Car(){
        System.out.println("car constructor...");
    }
    public void init(){
        System.out.println("car ... init...");
    }
    public void detory(){
        System.out.println("car ... detory...");
    }
}

注册到 IOC容器中:

//在 Bean 注解里面指定初始化和销毁方法
@Bean(initMethod="init",destroyMethod="detory")
public Car car(){
    return new Car();
}

2)通过让Bean实现

  • InitializingBean(定义初始化逻辑)
  • DisposableBean(定义销毁逻辑)

我们创建一个Cat类,实现InitializingBean 和 DisposableBean 两个接口:

@Component        //在配置类中开启包扫描,自动注册到 IOC 容器中
public class Cat implements InitializingBean,DisposableBean {
    public Cat(){
        System.out.println("cat constructor...");
    }
    public void afterPropertiesSet() throws Exception {
        //初始化方法
        System.out.println("cat...afterPropertiesSet...");
    }
    public void destroy() throws Exception {
        //销毁方法
        System.out.println("cat...destroy...");
    }
}

3)使用JSR250

  • @PostConstruct:在bean创建完成并且属性赋值完成,来执行初始化方法
  • @PreDestroy:在容器销毁bean之前通知我们进行清理工作

首先创建一个Dog类:

@Component        //在配置类中开启包扫描,自动注册到 IOC 容器中
public class Dog {
    public Dog(){
        System.out.println("dog constructor...");
    }
    //对象创建并赋值之后调用
    @PostConstruct
    public void init(){
        System.out.println("Dog....@PostConstruct...");
    }
    //容器移除对象之前
    @PreDestroy
    public void detory(){
        System.out.println("Dog....@PreDestroy...");
    }
}

4)BeanPostProcessor【interface】:bean的后置处理器

  • 在bean初始化前后进行一些处理工作;
  • postProcessBeforeInitialization:在初始化之前工作
  • postProcessAfterInitialization:在初始化之后工作

我们创建一个 MyBeanPostProcessor 类实现 BeanPostProcessor 接口:

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    //初始化前进行的操作
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization..."+beanName+"=>"+bean);
        return bean;
    }
    //初始化后进行的操作
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization..."+beanName+"=>"+bean);
        return bean;
    }
}

8)参数赋值

使用@Value赋值:

  1. 基本数值
  2. 可以写SpEL:#{}
  3. 可以写${} :取出配置文件【properties】中的值(在运行环境变量里面的值)


9)自动装配

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

一、@Autowired:自动注入

  1. 默认优先按照类型去容器中找对应的组件:

applicationContext.getBean(BookDao.class) 找到就赋值

  1. 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找:

    applicationContext.getBean("bookDao")

  2. 使用 @Qualifier 指定需要装配的组件的id,而不是使用属性名

  1. 自动装配默认一定要将属性赋值好,没有就会报错

    可以使用@Autowired(required=false)允许空装配

  1. 使用 @Primary:让Spring进行自动装配的时候,默认使用首选

​ 也可以继续使用 @Qualifier 指定需要装配的bean的名字,优先级比较高

**二、Spring还支持使用 @Resource(JSR250) 和 @Inject(JSR330) **

  1. @Resource
  • 可以和 @Autowired 一样实现自动装配功能;默认是按照组件名称进行装配的;
  • 不能支持 @Primary 功能且不能支持 @Autowired(reqiured=false)
  1. @Inject:
  • 需要导入 javax.inject 的包,和 **Autowired **的功能一样。没有 required=false 的功能;

三、@Autowired 标记位置 : 构造器,参数,方法,属性

构造器:如果组件只有一个有参构造器,这个有参构造器的 @Autowired 可以省略,参数位置的组件还是可以自动从容器中获取

参数(@Autowired 可以省略)

方法 :@Bean+方法参数;参数从容器中获取;默认不写@Autowired效果是一样的;都能自动装配

1)

2)

属性:

10)@Profile 指定环境

Spring为我们提供的可以根据当前环境,动态的激活和切换一系列组件的功能(开发环境、测试环境、生产环境…)

  • @Profile:指定组件在哪个环境的情况下才能被注册到容器中,不指定,任何环境下都能注册这个组件
  1. 加了环境标识的bean,只有这个环境被激活的时候才能注册到容器中。默认是default环境
  2. 写在配置类上,只有是指定的环境的时候,整个配置类里面的所有配置才能开始生效
  3. 没有标注环境标识的bean,在任何环境下都是加载的
  • 切换环境

    1)使用命令行动态参数: 在虚拟机参数位置加载 -Dspring.profiles.active=test

    2)代码的方式激活某种环境

//1、创建一个applicationContext
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
//2、设置需要激活的环境
applicationContext.getEnvironment().setActiveProfiles("dev");
//3、注册主配置类
applicationContext.register(MainConfigOfProfile.class);
//4、启动刷新容器
applicationContext.refresh();
看完不赞,都是坏蛋
看完不赞,都是坏蛋

今天的你多努力一点,明天的你就能少说一句求人的话!

我是小菜,一个和你一起学习的男人。 💋

posted @ 2020-07-05 16:23  蔡农曰  阅读(90)  评论(0编辑  收藏  举报