Spring

注解的方式注入Bean

官方定义:IoC又叫依赖注入(DI)。它描述了对象的定义和依赖的一个过程。依赖的对象通过构造参数、工厂方法参数或者属性注入,当对象实例化后依赖的对象才被创建,当创建bean后容器注入这些依赖对象。这个过程基本上是反向的。

方法详情

1.在Spring中,一个类我们为它加上注解就可以被识别为一个Bean。

例如你在一个类上加上一个@Component注解,它在配置类的@ComponentScan注解扫描的包下,或者把这给个类在配置类中加上@Bean注解,那么它就被识别为Bean,加入到Spring容器里。

@Component
public class FirstBean {

}

或者直接把这个类在Spring配置类里实例化然后使用@Bean注解。

@Configuration
@ComponentScan("com.imooc.spring.demo")
public class SpringBeanConfiguration {

    @Bean
    public FirstBean firstBean() {
        return new FirstBean();
    }
}
2.在一个Bean中调用另外一个Bean,就需要依赖注入。
@Component
public class SecondBean {
    private FirstBean firstBean;

    @Autowired
    public SecondBean(FirstBean firstBean) {
        this.firstBean = firstBean;
    }
    
    @Override
    public String toString() {
        return "SecondBean{firstBean=" + firstBean + '}';
    }
}

一个Bean要调用另一个Bean,直接调用是允许的,需要通过自动装配注解@Autowired进行依赖注入才能达成目的。

常用注解

注解

解释

@Configuration

标记的类是配置类

@ComponentScan(“包”)

指定哪个包,就扫描哪个包下的注解并识别。

@Autowired

Bean的自动装配,可以标注在类的属性、方法及构造函数上。

@Component

把普通类标记为Bean,加入到容器里,并且是单例模式。

@Bean

定义一个Bean对象,加入到Spring容器里

@Order(数字)

容器加载Bean的优先级,数字越小优先级越高

场景

我们将构造方法注入、工厂方法注入或者属性注入三种注入方式进行细化,依赖注入的方式具体如下:

  • 构造方法注入Bean
  • Set方法注入Bean
  • 属性注入Bean
  • 集合的方式注入

示例

首先通过Configuration和@ComponentScan创建一个Spring的配置类。

@Configuration
@ComponentScan("com.imooc.spring.demo.bean")//项目的包名
public class SpringBeanConfiguration {
}

新建一个类FirstBean,通过@Component注解标记为Bean,加入到Spring容器里。

@Component
public class FirstBean {

}

通过构造方法注入

@Component
public class SecondBean {
    private FirstBean firstBean;

    @Autowired
    public SecondBean(FirstBean firstBean) {
        this.firstBean = firstBean;
    }
    
    @Override
    public String toString() {
        return "SecondBean{firstBean=" + firstBean + '}';
    }
}

通过Set方法注入

@Component
public class ThirdBean {
    private FirstBean firstBean;

    @Autowired
    public void setFirstBean(FirstBean firstBean) {
        this.firstBean = firstBean;
    }

    @Override
    public String toString() {
        return "ThirdBean{firstBean=" + firstBean + '}';
    }
}

通过属性注入

@Component
public class FourthBean {
    @Autowired
    private FirstBean firstBean;

    @Override
    public String toString() {
        return "FourthBean{firstBean=" + firstBean + '}';
    }
}
属性注入时,private私有属性,Spring是通过反射去加载它到Spring容器里的。

通过集合注入Bean

新建一个类FifthBean,标记为Bean。 加入一个List类型 的属性,用@Autowired注入。
在配置类中对加入一个返回值为List的方法或者加两个返回String的方法,使用Bean注解,这样就完成集合的赋值。

@Component
public class FifthBean {
    @Autowired
    private List<String> stringList;

    public List<String> getStringList() {
        return stringList;
    }
}
@Configuration
@ComponentScan("com.imooc.spring.demo")
public class SpringBeanConfiguration {

    @Bean
    public List<String> stringList() {
        List<String> list = new ArrayList<>();
        list.add("hello");
        list.add("imooc");
        return list;
    }
}
@Configuration
@ComponentScan("com.imooc.spring.demo")
public class SpringBeanConfiguration {

    @Bean
    public String firstString() {
        return "bye";
    }
    @Bean
    public String secondString() {
        return "imooc";
    }
}
第二种方式的优先级高于第一种,两种同时存在时Spring默认使用第二种,若要控制优先级要使用@Order注解来控制优先级顺序。

测试方法

class BeanDeoTest {

    @Test
    public void test() {
        ApplicationContext applicationContext =
        AnnotationConfigApplicationContext(SpringBeanConfiguration.class);
        SecondBean secondBean = applicationContext.getBean("secondBean", SecondBean.class);
        ThirdBean thirdBean = applicationContext.getBean("thirdBean", ThirdBean.class);
        System.out.println(secondBean.toString());
        System.out.println(thirdBean.toString());
    }
}

ApplicationContext用来获取配置类,getBean函数用来获取指定的Bean对象。

Tips

1. 只有@ComponentScan扫描的包下的被@Component标记的类才能识别为Bean。
2. 测试时你会发现所有的FristBean对象都是一个地址,说明@Component是单例模式的。

知识对比

对比几种装配Bean的方式

XML注入

最原始的装配Bean的方式是XML语句,这也是Spring最早的注入方式。

<context:component-scan base-package="com.imooc.spring.demo"/>
<bean id="firstbean" class="FirstBean" />
代码方式注入

上文的测试类就是使用ApplicationContext进行上下文的获取,然后通过getBean进行Bean的注入。

ApplicationContext applicationContext = 
new AnnotationConfigApplicationContext(SpringBeanConfiguration.class);
SecondBean secondBean = applicationContext.getBean("secondBean", SecondBean.class);

注解注入的优点

  • 简洁明了,用注解代替大量的XML配置,降低了开发成本,节省了开发量。
  • 不用在.java文件和.xml文件中不断切换,提升开发的效率。

个人经验

  • 使用统一装配规则,开发时,一般使用统一的装配规则,要么就是全部注解方式,要么就是全部XML方式。然后搭配BeanFactory 或者 ApplicationContext进行Bean的注入。非特殊情况避免注解和XMl结合使用。
  • 推荐使用注解方式。当今互联网产品飞速迭代的情况下,成熟的互联网项目整体都是千万甚至上亿行代码,使用XML的成本会相当的高,注解已经是一种发展的趋势。