Spring中的依赖注入的三种方法
            基于构造方法
            setter注入(常用)
            接口注入(不常用)
Bean如下

package spring;

public class Role {
    private Long id;
    private String roleName;
    private String note;

    setter/getter...
}

构造注入配置

<bean id="role" class="spring.Role">
        <constructor-arg index="0" value="小红"></constructor-arg>
        <constructor-arg index="1" value="小红的描述"></constructor-arg>
    </bean>

其中index代表第几个参数,从0开始,value是为参数复制的值

setter注入:

<bean id="role" class="spring.Role">
        <constructor-arg index="0" value="小红"></constructor-arg>
        <constructor-arg index="1" value="小红的描述"></constructor-arg>
        <property name="roleName" value="熊明"></property>
        <property name="note" value="熊明的描述"></property>
    </bean>

这里也可以将构造配置去掉,这里没有去掉是为了验证,setter注入的值会将构造参数的值给覆盖

接口注入(因为配置较麻烦,故这里不讲解,不过可以提示通过JNDI的形式去获取)

Bean装配的3种方式
         1、在XML中显示配置
         2、在java的接口和类中实现配置(注解)
         3、隐式Bean的发现机制和自动装配原则
其使用优先顺序为:3>2>1
常用规则:注解为主,xml为辅助

待装配的Bean:

public class ComplexAssembly {
    private Long id;
    private List<String> list;
    private Map<String,String> map;
    private Set<String> set;
    private String[] array;
    private Properties properties;

    setter/getter...
}

Xml装配Bean

<bean id="complexAssembly" class="spring.ComplexAssembly">
        <property name="id" value="1"></property>
        <property name="list">
            <list>
                <value>list1</value>
                <value>list2</value>
                <value>list3</value>
            </list>
        </property>
        <property name="map">
            <map>
                <entry key="map1" value="map-value1"></entry>
                <entry key="map2" value="map-value2"></entry>
                <entry key="map3" value="map-value3"></entry>
            </map>
        </property>
        <property name="set">
            <set>
                <value>set1</value>
                <value>set2</value>
                <value>set3</value>
            </set>
        </property>

        <property name="array">
            <list>
                <value>array1</value>
                <value>array2</value>
            </list>
        </property>

        <property name="properties">
            <props>
                <prop key="prop1">value-prop-1</prop>
                <prop key="prop1">value-prop-2</prop>
            </props>
        </property>
    </bean>

通过注解装配Bean

@Component
public class Role1 {
    @Value("1")
    private Long id;
    @Value("小明")
    private String roleName;
    @Value("小明的描述")
    private String note;

    setter/getter...
}

注意:这里如果添加了带参构造方法,并且没有对应的Bean对象注入就会报错
No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {}
    

扫描类:

@ComponentScan(basePackages = "spring")
public class PojoConfig {

}

这里可以通过{“package1","package2"}来实现多个包的制定扫描

调用代码:

public class Main {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String string:
             beanDefinitionNames) {
            System.out.println(string);
        }
        Role1 bean = context.getBean(Role1.class);
        System.out.println(bean.getRoleName());
    };
}

ComponmentScan注解面临两个问题:
        需要实现扫名制定的类(采用basePackages解决)
        没有注入对象(采用@Autowired解决)

自动装配@Autowired

@Component(value = "roleService")
public class RoleService implements Service {
    @Autowired
    private Role1 role1 = null;

    @Override
    public void printInfo() {
        System.out.println(role1.getRoleName()+role1.getNote());
    }
    setter/getter...
}

调用代码:

public class Main {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String string:
             beanDefinitionNames) {
            System.out.println(string);
        }
        Role1 bean = context.getBean(RoleService.class);
        bean.printInfo();
    };
}

@Primary和@Qualifier消除自动装配的歧义性

public class Main {
    public static void main(String[] args) {

        ApplicationContext context = new AnnotationConfigApplicationContext(PojoConfig.class);
        String[] beanDefinitionNames = context.getBeanDefinitionNames();
        for (String string:
             beanDefinitionNames) {
            System.out.println(string);
        }
        Service bean = context.getBean(Service.class);
        bean.printInfo();
    };
}

该图中,Service是一个接口,如果该接口中有两个以上的实现类,都进行了IOC管理,那么这时候spring在使用自动装配的时候就会犯迷糊,所以我们要处理这种情况
@Primary可以实现优先注入,如果给一个类使用了该注解,那么当出现多个同类型Bean的时候,该类Bean优先被注入
@Qualifier可以指定按照名称来注入,不会出现上述问题

public class RoleController {
    @Autowired
    @Qualifier("roleService")
    private Service service;

    public Service getService() {
        return service;
    }

    public void setService(Service service) {
        this.service = service;
    }
}

上图代码,就可以确定,即使出现同一接口下的不同子类中,会将id=roleService的实例进行注入

使用@Bean装配Bean
      @Component不能够注解到方法上,所以就需要使用@Bean,该注解是将方法中的返回Bean交给IoC容器管理

@Bean(name = "dataSource")
    public DataSource getDataSource(){
        DataSource dataSource;
        ...
        return dataSource;
    }

这时候IOC容器在扫描它的时候就会得到一个dataSource对象,进而对其进行管理,通过@Bean注解也是可以实现自定义初始化方法和销毁方法的

装配混合使用
可以通过@ImportResource("classpath:spring-dataSource.xml")来在配置类中引入其他的xml配置文件,也可以通过在一个xml文件中通过<import resourse="spring-datasource.xml>导入另外一个xml配置文件,对于多个配置类,可以在一个配置类中通过@Import({ApplicationConfig2.class,ApplicationConfig3.class})来导入,而而配置类就是在类上加上注解@ComponentScan注解的类,该类不用实现

取代配置类的方式,在xml中配置

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"

       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <context:component-scan base-package="spring"/>
</beans>