[学习笔记] Spring之Spring IoC

# 学习 # · 2021-02-06

IoC实现之构造注入

1、创建User实体类:

//包含name、age两个属性及其getter/setter方法
//包含有参构造和无参构造方法
//包含say()输出方法
public class User {
    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    private int age;
    public int getAge() { return age; }
    public void setAge(int age) { this.age = age; }

    public User() {
        System.out.println("User类无参构造执行");
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public void say() {
        System.out.println("你好,我是" + name + ",今年" + age + "岁");
    }

}

2、编写Spring配置文件,注册Bean并注入参数:

<!--方法一:直接通过参数名设置-->
<bean id="user1" class="com.demo.pojo.User">
    <property name="name" value="Demo1"></property>
    <property name="age" value="1"></property>
</bean>

<!--方法二:下标赋值-->
<bean id="user2" class="com.demo.pojo.User">
    <constructor-arg index="0" value="demo2"></constructor-arg>
    <constructor-arg index="1" value="2"></constructor-arg>
</bean>

<!--方法三:类型赋值,不建议使用-->
<bean id="user3" class="com.demo.pojo.User">
    <constructor-arg type="java.lang.String" value="demo3"></constructor-arg>
    <constructor-arg type="int" value="3"></constructor-arg>
</bean>

3、创建测试类,调试并输出:

@Test
public void run() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    User user = (User) context.getBean("user1");
    user.say();
}

4、设值注入和构造注入的特点:

(1)设值注入:通过setter访问器实现,灵活性好,但setter方法数量较多,时效性差,通过无参构造实例化。

(2)构造注入:通过构造方法实现,灵活性差,仅靠重载限制太多,时效性好,通过匹配的构造方法实例化。


IoC实现之Set方式注入(注入不同数据类型)

1、注入直接量(基本数据类型、字符串):

<!-- 使用<value>子元素注入 -->
<property name="name">
    <value>张三</value>
</property>

<!-- 使用<![CDATA[]]>标记处理XML特殊字符 -->
<property name="specialCharacter1">
    <value><![CDATA[P&G]]></value>
</property>

<!-- 把XML特殊字符替换为实体引用 -->
<property name="specialCharacter2">
    <value>P&amp;G</value>
</property>

2、注入其他Bean组件:

<!-- 定义UserDao对象,并指定id为userDao -->
<bean id="userDao" class="com.demo.dao.UserDaoImpl" />

<!-- 定义UserServiceImpl对象,并指定id为userService -->
<bean id="userService" class="com.demo.service.impl.UserServiceImpl">
    <!-- 为userService的Dao属性赋值,调用setDao()方法 -->
    <property name="dao">
        <!-- 方法一:引用id为userDao的对象为userService的dao属性赋值 -->
        <ref bean="userDao" />

        <!-- 方法二:与bean属性用法相似,但local只能在同一个配置文件中检索Bean的id -->
        <ref local="userDao" />
    </property>
</bean>

3、使用内部Bean:

<!-- 定义UserServiceImpl对象,并指定id为userService -->
<bean id="userService" class="com.demo.service.impl.UserServiceImpl">
    <!--为UserService的dao属性赋值,,调用setDao()方法-->
    <property name="dao">
        <!-- 定义UserDao对象 -->
        <!-- 此时UserDaoImpl类型的Bean就只能被userService调用,无法被其他Bean引用 -->
        <bean class="com.demo.dao.UserDaoImpl" />
    </property>
</bean>

4、注入集合类型的属性:

<!-- 注入List类型 -->
<property name="list">
    <list>
        <!-- 定义List中的元素 -->
        <value>足球</value>
        <value>篮球</value>
    </list>
</property>

<!-- 注入数组类型 -->
<property name="array">
    <list>
        <!-- 定义数组中的元素 -->
        <value>足球</value>
        <value>篮球</value>
    </list>
</property>

<!-- 注入Set类型 -->
<property name="set">
    <set>
        <!-- 定义Set或数组中的元素 -->
        <value>足球</value>
        <value>篮球</value>
    </set>
</property>

<!-- 注入Map类型 -->
<property name="map">
    <map>
        <!-- 定义Map中的键值对 -->
        <entry>
            <key>
                <value>football</value>
            </key>
            <value>足球</value>
        </entry>
        <entry>
            <key>
                <value>basketball</value>
            </key>
            <value>篮球</value>
        </entry>
    </map>
</property>

<!-- 注入Properties类型 -->
<property name="props">
    <props>
        <!-- 定义Properties中的键值对 -->
        <prop key="football">足球</prop>
        <prop key="basketball">篮球</prop>
    </props>
</property>

5、注入null和空字符串值:

<!-- 注入空字符串值 -->
<property name="emptyValue">
    <value></value>
</property>

<!-- 注入null值 -->
<property name="nullValue">
    <null/>
</property>

IoC实现之使用c命名和p命名空间注入

1、p命名空间的特点:使用属性而不是子元素的形式配置Bean的属性,从而简化Bean的配置。

2、p命名空间的基本语法:相当于property

<!-- 使用p命名空间注入属性值 -->
<bean id="user4" class="com.demo.pojo.User" p:name="demo4" p:age="4"></bean>

3、c命名空间的基本语法:相当于constructor

<bean id="user5" class="com.demo.pojo.User" c:name="demo5" c:age="5"></bean>

IoC实现之XML配置自动装配

1、自动装配是Spring满足bean依赖的一种方式,Spring会在上下文中自动寻找,并自动给bean装配属性。

2、搭建测试环境:

(1)创建持久化类:猫类、狗类、人类。

/**
 * 人类
 */
public class Person {
    private Cat cat;
    public Cat getCat() { return cat; }
    public void setCat(Cat cat) { this.cat = cat; }

    private Dog dog;
    public Dog getDog() { return dog; }
    public void setDog(Dog dog) { this.dog = dog; }

    private String name;
    public String getName() { return name; }
    public void setName(String name) { this.name = name; }

    public void say() {
        System.out.println("我是" + name);
    }
}

(2)编写Spring配置文件,注册相关的Bean:

<bean id="cat" class="com.demo.pojo.Cat"></bean>
<bean id="dog" class="com.demo.pojo.Dog"></bean>
<bean id="person" class="com.demo.pojo.Person">
    <property name="name" value="小红"></property>
    <property name="cat" ref="cat"></property>
    <property name="dog" ref="dog"></property>
</bean>

(3)创建测试类:

@Test
public void run() {
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    Person p = (Person) context.getBean("person");
    p.getCat().say();    //输出:猫
    p.getDog().say();    //输出:狗
}

3、方法一:ByName实现自动装配。

<!--
    ByName:会自动在容器上下文中查找和自己对象set方法后面的值对应的bean id。
-->
<bean id="person" class="com.demo.pojo.Person" autowire="byName">
    <property name="name" value="小红"></property>
</bean>

4、方法二:ByType实现自动装配。

<!--
    ByType:会自动在容器上下文中查找和自己对象属性类型相同的bean id。
-->
<bean id="person" class="com.demo.pojo.Person" autowire="byType">
    <property name="name" value="小红"></property>
</bean>

IoC实现之注解配置自动装配

1、方法一:使用@Autowired注解。使用该注解,可以不用编写setter方法,前提是这个自动装配的属性在IoC (Spring)容器中存在,且符合名字ByName。

(1)修改Person持久化类,使用注解。

@Autowired
private Cat cat;
public Cat getCat() { return cat; }
public void setCat(Cat cat) { this.cat = cat; }

(2)修改String配置文件,激活注解。

<!-- 方法一:用于激活那些已经在spring容器里注册过的bean上面的注解 -->
<context:annotation-config></context:annotation-config>

<!-- 方法二:指定要扫描的包,这个包下的注解就会自动生效,多个包用逗号隔开 -->
<context:component-scan base-package="com.demo.pojo"></context:component-scan>

(3)@Autowired注解也可以对方法或构造方法的入参进行标注。

private Cat cat;
@Autowired
public void setCat(Cat cat) { this.cat = cat; }

(4)如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解@Autowired完成的时候,可以使@Qualifier()注解配置@Autowired的使用,指定一个唯一的bean对象注入。

@Autowired
public Person(@Qualifier("cat") Cat cat) {
    this.cat = cat;
}

2、方法二:使用@Resource注解。Spring还支持JSR-250中定义的@Resource注解实现组件装配。

(1)修改Person持久化类,使用注解。

@Resource
private Cat cat;
public Cat getCat() { return cat; }
public void setCat(Cat cat) { this.cat = cat; }

3、@Resource注解和@Autowired注解的区别:

(1)都是用来自动装配的,都可以放在属性字段上。

(2)@Autowired注解通过ByType的方式实现,而且必须要求这个对象存在。

(3)@Resource默认通过ByName的方式实现,如果找不到名字,则通过byType实现。如果两个都找不到的情况下则报错。

(4)执行顺序不同:@Autowired通过byType的方式实现。

如无特殊说明,本博所有文章均为博主原创。

如若转载,请注明出处:一木林多 - https://www.l5v.cn/archives/215/

评论