黑马程序员技术交流社区

标题: 【上海校区】Spring学习之路2-依赖注入及bean相关知识 [打印本页]

作者: 梦缠绕的时候    时间: 2020-3-18 09:31
标题: 【上海校区】Spring学习之路2-依赖注入及bean相关知识
依赖注入
不同数据类型的注入方式

public class Student {
    private String name;
    private Address address;
    private String[] stationeries;
    private List<String> hobbies;
    private Map<String, String> book;
    private Set<String> games;
    private String wife;
    private Properties info;
    ...
<bean id="address" class="com.youzi.pojo.Address">
    <property name="address" value="China"/>
</bean>

<bean id="student" class="com.youzi.pojo.Student">
    <property name="name" value="张三"/>
    <property name="address" ref="address"/>
    <property name="stationeries">
        <array>
            <value>ruler</value>
            <value>eraser</value>
            <value>pencil</value>
        </array>
    </property>
    <property name="wife">
        <null/>
    </property>
    <property name="book">
        <map>
            <entry key="西游记" value="吴承恩"/>
            <entry key="红楼梦" value="曹雪芹"/>
        </map>
    </property>
    <property name="games">
        <set>
            <value>LOL</value>
            <value>COD</value>
            <value>CS</value>
        </set>
    </property>
    <property name="hobbies">
        <list>
            <value>sing</value>
            <value>dance</value>
            <value>rap</value>
            <value>basketball</value>
        </list>
    </property>
    <property name="info">
        <props>
            <prop key="userName">zhangsan</prop>
            <prop key="cardNo">12345678</prop>
        </props>
    </property>
</bean>
除了通过 setter 注入、构造器注入还可以通过类似的 p-namespace 和 c-namespace 进行注入,具体参看官方文档的例子,使用命名空间注入

Bean 作用域
Scope        Description
singleton        (Default) Scopes a single bean definition to a single object instance for each Spring IoC container.
prototype        Scopes a single bean definition to any number of object instances.
request        Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext.
session        Scopes a single bean definition to the lifecycle of an HTTP Session. Only valid in the context of a web-aware Spring ApplicationContext.
application        Scopes a single bean definition to the lifecycle of a ServletContext. Only valid in the context of a web-aware Spring ApplicationContext.
websocket        Scopes a single bean definition to the lifecycle of a WebSocket. Only valid in the context of a web-aware Spring ApplicationContext.
Bean 的自动装配
自动装配是 Spring 满足 bean 依赖的一种方式
Spring 会在上下文中自动寻找,并自动给 bean 装配属性
Spring 中有三种装配方式

再 xml 中显式地配置
再 Java 中显式地配置
隐式的自动装配 bean
xml 中显式的配置

public class People {
    private String name;
    private Animal cat;
    private Animal Dog;
    ...
public class Cat implements Animal {
    @Override
    public void bark() {
        System.out.println("miao~");
    }
}
public class Dog implements Animal {
    @Override
    public void bark() {
        System.out.println("wang~");
    }
}
<bean id="cat" class="com.youzi.pojo.Cat"/>
<bean id="dog" class="com.youzi.pojo.Dog"/>

<bean id="people1" class="com.youzi.pojo.People">
    <property name="name" value="zhangsan"/>
    <property name="cat" ref="cat"/>
    <property name="dog" ref="dog"/>
</bean>
隐式的自动装配 bean

通过名字自动装配,bean id 要和对应的 setter 方法名对应,且首字母小写,如 setAbc() 对应的 bean id 就应该为 abc
<bean id="cat" class="com.youzi.pojo.Cat"/>
<bean id="dog" class="com.youzi.pojo.Dog"/>

<bean id="people1" class="com.youzi.pojo.People" autowire="byName">
    <property name="name" value="zhangsan"/>
</bean>
通过类型自动装配,需要参数为不同的类型才能使用,不然会报错 NoUniqueBeanDefinitionException 也就是当前示例中的 cat 和 dog 不能再使用 Animal 声明,应改为

private Cat cat;

private Dog dog;

<bean id="cat" class="com.youzi.pojo.Cat"/>
<bean id="dog" class="com.youzi.pojo.Dog"/>

<bean id="people1" class="com.youzi.pojo.People" autowire="byType">
    <property name="name" value="zhangsan"/>
</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"
       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
       https://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>

    <bean id="cat" class="com.youzi.pojo.Cat"/>
    <bean id="dog" class="com.youzi.pojo.Dog"/>

    <bean id="people1" class="com.youzi.pojo.People">
        <property name="name" value="zhangsan"/>
    </bean>
</beans>
代码中只需要加上 @Autowired 即可实现自动装配 bean

正确使用该方式的情况下可以不声明 setter 也能自动装配,与上面的 xml 不同

装配的方式为先按类型,再按名字

如果 cat 声明为 Cat 类型,即 cat 和 dog 为不同类型的时候,那么 bean id 和属性不用同名(setter 可有可无所以也不用同名),类似于 xml 中的 autowire="byType"

如果 cat 和 dog 为相同类型的时候,如代码中都声明为 Animal 类型,那么会通过名字去匹配,需要bean id 和属性名字相同,相当于 xml 中的 autowire="byName"

public class People {
    private String name;
    @Autowired
    private Animal cat;
    @Autowired
    private Animal dog;
    ...
如果存在多个 bean 想装配其中指定的某个的时候,可以使用 @Qualifier 注解实现

public class People {
    private String name;
    @Autowired
    private Animal cat;
    @Autowired
    @Qualifier("dog2")  //指定使用 dog2
    private Animal dog;
    ...
<bean id="dog1" class="com.youzi.pojo.Dog" scope="prototype">
    <property name="sound" value="wang~"/>
</bean>
<bean id="dog2" class="com.youzi.pojo.Dog" scope="prototype">
    <property name="sound" value="wangwang~"/>
</bean>
也可以使用 @Resource 注解实现上述功能,功能和 @Autowired 相同,不过可以直接指定 bean id

import javax.annotation.Resource;

public class People {
    private String name;
    //@Autowired
    @Resource
    private Animal cat;
    //@Autowired
    //@Qualifier("dog2")
    @Resource
    private Animal dog;
    ...


作者: 梦缠绕的时候    时间: 2020-3-18 09:31
有问题欢迎添加小优微信
DKA-2018




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2