Spring:Bean的装配方式记录

Bean的装配相当于依赖关系的注入,Bean的装配方式即Bean依赖注入的方式。一切即Bean,Bean即一切。

Spring容器支持多种形式的装配方式,如基于XML的装配、基于注解(Annotation)的装配和自动装配等(其中最常用的是基于注解的装配)。

一、基于XML的装配

(1)设值注入(Setter Injection)

在Spring实例化Bean的过程中,Spring首先会调用Bean的默认构造方法来实例化Bean对象,然后通过反射的方式调用setter方法来注入属性值。因此,设值注入要求一个Bean必须满足以下两点要求:

①Bean类必须提供一个默认的无参构造方法。

②Bean类必须为需要注入的属性提供对应的setter方法。

在使用设值注入时,Spring配置文件中需要使用<bean>元素的子元素<property>来为每个属性注入值。

示例】:

public class User {
    private String username;
    private Integer password;
    private List<String> list;

    // 使用设值注入
    // 1.提供默认无参构造方法
    // 2.为所有属性提供setter方法

    public User() {
        super();
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(Integer password) {
        this.password = password;
    }

    public void setList(List<String> list) {
        this.list = list;
    }
    
    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password + 
                ", list=" + list + "]";
    }
}

创建装配文件beans1.xml,在配置文件中通过设值注入的方式装配User类的实例,如下所示:

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

    <!-- 使用设值注入方式装配User实例-->
    <bean id="user1" class="com.py.model.User">
        <property name="username" value="张三"></property>
        <property name="password" value="654321"></property>
        <!--注入list集合-->
        <property name="list">
            <list>
                <value>"setlistvalue1"</value>
                <value>"setlistvalue2"</value>
            </list>
        </property>
    </bean>
</beans>

创建测试类XmlBeanAssembleTest,在类中获取并输出user1实例:

public class XmlBeanAssembleTest {
    public static void main(String[] args) {
        String xmlPath = "beans1.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        System.out.println(applicationContext.getBean("user1"));

    }
}

输出结果:

(2)构造注入

示例】:

public class User {
    private String username;
    private Integer password;
    private List<String> list;

    //构造注入
    //提供带所有参数的有参构造方法

    public User(String username,Integer password, List<String> list) {
        super();
        this.username = username;
        this.password = password;
        this.list = list;
    }
    

    @Override
    public String toString() {
        return "User [username=" + username + ", password=" + password +
                ", list=" + list + "]";
    }
}

 在使用构造注入时,在配置文件中需要使用<bean>元素的子元素<constructor-arg>来定义构造方法的参数,可以使用其value属性(或子元素)来设置该参数的值。

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

    <!-- 使用构造注入的方式装配User实例-->
    <bean id="user2" class="com.py.model.User">
        <constructor-arg index="0" value="李四" />
        <constructor-arg index="1" value="123456" />
        <constructor-arg index="2">
            <list>
                <value>"constructorvalue1"</value>
                <value>"constructorvalue2"</value>
            </list>
        </constructor-arg>
    </bean>
</beans>

修改XmlBeanAssembleTest类:

public class XmlBeanAssembleTest {
    public static void main(String[] args) {
        String xmlPath = "beans2.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);

        System.out.println(applicationContext.getBean("user2"));

    }
}

输出结果:

 

二、基于Annotation的装配

 在应用中Bean较多时,使用XML配置文件实现Bean的装配工作可能会造成XML配置文件过于臃肿,给后续的维护和升级工作会带来一定的困难。Spring提供了对Annotation(注解)技术的全面支持。

 Spring中定义了一系列的注解,常用注解如下:

  • @Component

可以使用此注解描述Spring中的Bean,但它是一个泛化的概念,仅仅表示一个组件(Bean),并且可以作用在任何层次。使用时只需将该注解标注在相应的类上即可。

  • @Repository

用于数据访问层(DAO层)的类标识为Spring中的Bean,其功能与@Component相同。

  • @Service

通常作用在业务层(Service层),用于将业务层的类标识为Spring中的Bean,其功能与@Component相同。

  • @Controller

通常作用在控制层(如SpringMVC的Controller),用于将控制层的类标识为Spring中的Bean,其功能与@Component相同。

  • @Autowired

用于对Bean的属性变量、属性的setter方法及构造方法进行标注,配合对应的注解处理器完成Bean的自动配置工作。默认按照Bean的类型进行装配。

  • @Resource

其作用与Autowired一样。其区别在于@Autowired默认按照Bean类型装配,而@Resource默认按照Bean实例名称进行装配。@Resource中有两个重要属性:name和type。Spring将name属性解析为Bean实例名称,type属性解析为Bean实例类型。如果指定name属性,则按实例名称进行装配;如果指定type属性,则按Bean类型进行装配;如果都不指定,则先按Bean实例名称装配,如果不能匹配,再按照Bean类型进行装配;如果都无法匹配,则抛出NoSuchBeanDefinitionException异常。

  • @Qualifier

与@Autowired注解配合使用,会将默认的按Bean类型装配修改为按Bean的实例名称装配,Bean的实例名称由@Qualifier注解的参数指定。

上述注解中的@Repository、@Service与@Controller功能与@Component注解的功能相同,但为了使注解类本身用途更加清晰,建议在实际开发中使用@Repository、@Service与@Controller分别对实现类进行标注。

示例】:

步骤一:创建接口UserDao,并在接口中定义一个save()方法

public interface UserDao {
    void save();
}

步骤二:创建UserDao接口的实现类UserDaoImpl,该类需要实现接口中的save()方法

@Repository("userDao")
public class UserDaoImp implements UserDao {
    public void save() {
        System.out.println("userdao...save...");
    }
}

使用@Repository注解将UserDaoImpl类标识为Spring中的Bean,相当于在配置文件中编写如下语句:

<bean id="userDao" class="com.py.example.dao.impl.UserDaoImpl" />

步骤三:创建接口UserService,在接口中同样定义一个save()方法

public interface UserService {
    void save();
}

步骤四:创建UserService接口的实现类UserServiceImpl,该类需要实现接口中的save()方法

@Service("userService")
public class UserServiceImpl implements UserService {

    @Resource(name="userDao")
    private UserDao userDao;

    @Override
    public void save() {
        this.userDao.save();
        System.out.println("userservice...save...");
    }
}

使用@Service注解将UserServiceImp类 标识为Spring中的Bean,相当于在配置文件中编写如下语句:

<bean id="userService" class="com.py.example.service.UserServiceImpl" />

然后使用@Resource注解标注在属性userDao上,相当于在配置文件中编写如下语句:

<property name="userDao" ref="userDao" />

步骤五:创建控制器类UserController

@Controller("userController")
public class UserController {

    @Resource(name="userService")
    private UserService userService;

    public void save() {
        this.userService.save();
        System.out.println("userController...save...");
    }
}

 使用@Controller注解标注UserController类,相当于配置文件编写如下语句:

<bean id="userController" class="com.py.example.controller" />

然后使用@Resource注解标注在userService属性上,相当于配置文件编写如下语句:

<property name="userService" ref="userService" />

步骤六:创建配置文件beans3.xml,在配置文件中编写基于Annotation装配的代码

<?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命名空间,在配置文件中开启相应的注解处理器-->
    <context:annotation-config />
    
    <!--分别定义三个Bean实例-->
    <bean id="userDao" class="com.py.example.dao.impl.UserDaoImp"/>
    <bean id="userService" class="com.py.example.service.impl.UserServiceImpl" />
    <bean id="userController" class="com.py.example.controller.UserController" />

</beans>

与XML装配方式不同的是,这里不需要再配置子元素<property>,虽然上述Spring配置文件中的注解方式较大程度地简化了XML文件中Bean的配置,但仍需要在Spring配置文件中一一配置相应的Bean,为此Spring注解提供了另一种高效的注解配置方式(对包路径下的所有Bean文件进行扫描),其配置方式如下:

<context:component-scan base-package="Bean所在的包路径">

 ***上述的Spring配置文件即可改写为如下形式***

<?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命名空间,通知Spring扫描指定包下所有Bean类,进行注解解析-->
    <context:component-scan base-package="com.py.example" />

</beans>

步骤七:创建测试类AnnotationAssembleTest,在类中编写测试方法并定义配置文件的路径,通过Spring容器加载配置文件并获取UserController实例,最后调用实例中的save()方法。

public class AnnotationAssembleTest {

    public static void main(String[] args) {
        String xmlPath = "beans3.xml";
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
        UserController userController = (UserController) applicationContext.getBean("userController");
        userController.save();
    }
}

输出结果:

 

三、自动装配

所谓自动装配,就是将一个Bean自动地注入到其他Bean的property中。Spring的<bean>元素中包含一个autowire属性,可以通过设置autowire的属性来自动装配Bean。

autowire属性有如下5个值:

  • default(默认值)

由<bean>的上级标签<beans>的default-autowire属性值确定。例如<beans default-autowire="byName">,则该<bean>元素中的autowire属性对应的属性值就为byName

  • byName

根据属性的名称自动装配。容器将根据名称查找与属性完全一致的Bean,并将其属性自动装配

  • byType

根据属性的数据类型(Type)自动装配,如果一个Bean的数据类型,兼容另一个Bean中属性的数据类型,则自动装配

  • constructor

根据构造函数参数的数据类型,进行byType模式的自动装配

  • no

在默认情况下,不使用自动装配,Bean依赖必须通过ref元素定义

示例】:

步骤一:先修改上节中编写的UserServiceImpl和UserController类,分别增加类属性的setter方法。

步骤二:修改beans3.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">

    <!-- 使用bean元素的autowire属性完成自动装配-->
    <bean id="userDao" class="com.play.UserDaoImpl"/>
    <bean id="userService" class="com.play.UserServiceImpl" autowire="byName"/>
    <bean id="userController" class="com.play.UserController" autowire="byName"/>

</beans>

步骤三:执行程序,控制台输出结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值