spring之依赖关系处理方式

前言

我们知道spring框架的核心就是IOC容器了,那么IOC容器主要的作用就是创建对象和处理对象之间的依赖关系。上次介绍了创建对象的集中方式,那么本文主要延续上一节内容,讲解IOC容器如何处理对象之间的依赖关系。

依赖注入(DI)

依赖注入是通过IOC容器将指定的依赖对象或者基本类型的变量注入指定的对象中。这么说比较抽象。比如:之前的mvc设计模式,在action中需要调用service层的方法,就必须由程序员自己new一个service实例,然后才能使用,即action必须依赖service才能实现业务。还有这种new一个对象,硬编码的方式也不利于维护。现在有了IOC容器,可以由容器帮助我们创建对象以及处理对象之间的依赖关系。所有事都交给容器来管理。我们只管会配置会使用它即可。

依赖注入的方式

(1)set方式注入(最常用)

<!-- dao instance -->
    <bean id="userDao" class="com.nwpu.geeker.UserDao"></bean>

    <!-- service instance -->
    <bean id="userService" class="com.nwpu.geeker.UserService">
        <property name="userDao" ref="userDao"></property>
    </bean>

    <!-- action instance -->
    <bean id="userAction" class="com.nwpu.geeker.UserAction">
        <property name="userService" ref="userService"></property>
    </bean>

**注意:**set方式最常用也是必须得掌握的。因为在实现开发中,mvc设计模式下dao层是数据访问接口层,service是业务逻辑层,在处理业务逻辑的时候,必须要和数据打交道。那么就必须依赖于dao层的方法。因此必须在service层依赖dao层的对象。而Action层也必须依赖service层处理业务。所以,上面配置是将userDao注入到userService中,将userService注入到userAction中。Ref属性必须是已存在于IOC容器的对象才能直接引用。

(2)内部bean方式

<bean id="userAction" class="com.nwpu.geeker.UserAction">
        <property name="userService">
            <bean class="com.nwpu.geeker.UserService">
                <property name="userDao">
                    <bean class="com.nwpu.geeker.UserDao"></bean>
                </property>
            </bean>
        </property>
    </bean>

内部bean的方式主要是定义一个bean就能实现这个bean所依赖的对象的所有方法。缺点就是只能使用外部的bean,内部的bean不能使用。例如:只能使用userAction,而不能使用里面bean,userService实例。

(3)p 名称空间注入属性值 (优化)

<?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:p="http://www.springframework.org/schema/p"
    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">

    <!-- 
        给对象属性注入值:
            # p 名称空间给对象的属性注入值
             (spring3.0以上版本才支持)
     -->
     <bean id="userDao" class="com.nwpu.geeker.UserDao"></bean>

     <bean id="userService" class="com.nwpu.geeker.UserService" p:userDao-ref="userDao"></bean>

     <bean id="userAction" class="com.nwpu.geeker.UserAction" p:userService-ref="userService"></bean>


    <!-- 传统的注入: 
     <bean id="user" class="com.nwpu.geeker.User" >
        <property name="name" value="xxx"></property>
     </bean>
    -->
    <!-- p名称空间优化后 -->
    <bean id="user" class="com.nwpu.geeker.User" p:name="Jack001"></bean>

</beans>   

P名称空间注入方式必须在配置文件中添加 xmlns:p="http://www.springframework.org/schema/p"
,直接在《bean》标签中使用p属性即可,很方便。

(4)自动装配(了解)

根据名称自动装配:autowire=”byName”,自动去IOC容器中找与属性名同名的引用的对象,并自动注入。

<!-- ###############自动装配############### -->  
    <bean id="userDao" class="com.nwpu.geeker.UserDao"></bean>  
    <bean id="userService" class="com.nwpu.geeker.UserService" autowire="byName"></bean>
    <!-- 根据“名称”自动装配: userAction注入的属性,会去ioc容器中自动查找与属性同名的对象 -->
    <bean id="userAction" 
class="com.nwpu.geeker.UserAction" autowire="byName"></bean>

也可以定义到全局, 这样就不用每个bean节点都去写autowire=”byName”

<?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:p="http://www.springframework.org/schema/p"
    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" default-autowire="byName">   根据名称自动装配(全局)

    <!-- ###############自动装配############### -->  
    <bean id="userDao" class="com.nwpu.geeker.UserDao"></bean>  
    <bean id="userService" class="com.nwpu.geeker.UserService"></bean>
    <bean id="userAction" class="com.nwpu.geeker.UserAction"></bean>
</beans>   

根据类型自动装配:autowire=”byType”,必须确保改类型在IOC容器中只有一个对象;否则报错。

<?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:p="http://www.springframework.org/schema/p"
    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" default-autowire="byType">

    <!-- ###############自动装配############### -->  
    <bean id="userDao" class="com.nwpu.geeker.UserDao"></bean>  
    <bean id="userService" class="com.nwpu.geeker.UserService"></bean>

    <!-- 如果根据类型自动装配: 必须确保IOC容器中只有一个该类型的对象 -->
    <bean id="userAction" class="com.nwpu.geeker.UserAction"></bean>


    <!--   报错: 因为上面已经有一个该类型的对象,且使用了根据类型自动装配
    <bean id="userService_test" class="com.nwpu.geeker.UserService" autowire="byType"></bean>
     -->
</beans>  

总结:
Spring提供的自动装配主要是为了简化配置; 但是不利于后期的维护。(一般不推荐使用)

(5)注解
注解方式可以简化spring的IOC容器的配置!

使用注解步骤:
1)先在配置文件中引入context名称空间

xmlns:context="http://www.springframework.org/schema/context"

2)开启注解扫描(指定扫描的包)

<context:component-scan base-package="com.nwpu.geeker"></context:component-scan>

3)使用注解
通过注解的方式,把对象加入ioc容器。

创建对象以及处理对象依赖关系,相关的注解如下:

@Component    指定把一个对象加入IOC容器
@Repository   作用同@Component; 在持久层使用
@Service      作用同@Component; 在业务逻辑层使用
@Controller   作用同@Component; 在控制层使用 
@Resource     属性注入

代码演示:
dao层

// 把当前对象加入ioc容器
//@Component("userDao")   //  相当于bean.xml 【<bean id=userDao class=".." />】

//@Component  // 加入ioc容器的UserDao对象的引用名称, 默认与类名一样, 且第一个字母小写

//@Repository   // 在持久层可以选择用这个注解
public class UserDao {

    public UserDao(){
        System.out.println("UserDao.UserDao()");
    }

    public UserDao(int id){
        System.out.println("UserDao.UserDao(int id)" + id);
    }

    public void save() {
        System.out.println("DB:保存用户!!!");
    }
}

service层

//@Component("userService")  // userService加入ioc容器

//@Component

@Service   // 表示业务逻辑层的组件
public class UserService {

//  @Resource                   //  根据类型查找 【在容器中要确保该类型只有一个变量】

    @Resource(name = "userDao")  // 根据名称查找
    private UserDao userDao;  // 去容器中找UserDao类型的变量,找到后就赋值

    public void save() {
        userDao.save();
    }
}

action层

//@Component("userAction")  // 加入IOC容器

//@Component

@Controller  // 控制层的组件
public class UserAction {

    @Resource
    private UserService userService;

    public String execute() {
        userService.save();
        return null;
    }
}

总结:
1) 使用注解,可以简化配置,且可以把对象加入IOC容器,及处理依赖关系(DI)
2) 注解可以和XML配置一起使用。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值