Spring IoC 基于注解的开发

Posted 好多个码农

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Spring IoC 基于注解的开发相关的知识,希望对你有一定的参考价值。

前言

前面内容对 Spring IoC 的基本使用做了详细的讲解,这一讲来学习 IoC 在实际开发中的应用,通过 IoC 容器可以更好地构建程序的分层结构,基本原理是 IoC 提供了各个组件的实例化对象,然后根据具体需求从 IoC 中取出相应组件完成依赖注入,就类似于搭积木,IoC 把零件提供好了,我们只需要进行组装即可。

实现方式有两种:基于 XML 配置文件和基于注解。

具体思路如下:把程序分为 Controller 层、Service 层和 DAO 层三层。

关系为 Controller 层调用 Service 层,Service 层调用 DAO 层,并且 Service 层和 DAO 层设计为接口,这是一个典型的 MVC 模式后台代码分层结构。

接下来我们学习两种实现方式的具体使用。

基于 XML 配置方式

(1)创建 UserController 类

public class UserController {

    private UserService userService;

    public User getUserById(int id){
        return userService.getUserById(id);
    }

}


(2)创建 UserService 接口以及实现类 UserServiceImpl

public interface UserService {
    public User getUserById(int id);
}

public class UserServiceImpl implements UserService{

    private UserDAO userDAO;

    @Override
    public User getUserById(int id) {
        // TODO Auto-generated method stub
        return userDAO.getUserById(id);
    }

}


(3)创建 UserDAO 接口以及实现类 UserDAOImpl

public interface UserDAO {
    public User getUserById(int id);
}

public class UserDAOImpl implements UserDAO{

    private static Map<Integer,User> users;

    static{
        users = new HashMap<Integer,User>();
        users.put(1, new User(1, "张三"));
        users.put(2, new User(2, "李四"));
        users.put(3, new User(3, "王五"));
    }

    @Override
    public User getUserById(int id) {
        // TODO Auto-generated method stub
        return users.get(id);
    }

}


(4)创建 User 实体类

public class User {
    private int id;
    private String name;
    public User(int id, String name) {
        super();
        this.id = id;
        this.name = name;
    }
}


(5)在 spring.xml 配置 userController、userService、userDAO,并完成依赖注入。

<!-- 配置UserController -->
<bean id="userController" class="com.southwind.controller.UserController">
    <property name="userService" ref="userService"></property>
</bean>
<!-- 配置UserService -->
<bean id="userService" class="com.southwind.service.impl.UserServiceImpl">
    <property name="userDAO" ref="userDAO"></property>
</bean>
<!-- 配置UserDAO -->
<bean id="userDAO" class="com.southwind.dao.impl.UserDAOImpl"></bean>


(6)在测试类中获取 userController 对象,调用方法获取 user 对象。

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserController userController = (UserController) applicationContext.getBean("userController");
User user = userController.getUserById(1);
System.out.println(user);


运行结果如下图所示。

基于注解的方式

第一步:将 UserController、UserService 和 UserDAO 类扫描到 IoC 容器中。

第二步:在类中设置注解完成依赖注入。

(1)修改 spring.xml

<!-- 将类扫描到 IoC 容器中 -->
<context:component-scan base-package="com.southwind"></context:component-scan>


base-package="com.southwind" 表示将 "com.southwind" 下所有子包的类全部扫描到 IoC 容器中,一步可将所有参与项目的类完成扫描注入。注意:配置文件需要引入 context 命名空间。

(2)修改 UserController,添加注解

@Controller
public class UserController {

    @Autowired
    private UserService userService;

    public User getUserById(int id){
        return userService.getUserById(id);
    }

}


对比之前的代码,有两处改动:

  • 在类名处添加 @Controller 注解,表示该类作为一个控制器;

  • userService 属性处添加 @Autowired 注解,表示 IoC 容器自动完成装载,默认是 byType 的方式。

(3)修改 UserServiceImpl

@Service
public class UserServiceImpl implements UserService{

    @Autowired
    private UserDAO userDAO;

    @Override
    public User getUserById(int id) {
        // TODO Auto-generated method stub
        return userDAO.getUserById(id);
    }

}


同上,做了两处改动:

  • 在类名处添加 @Service 注解,表示该类是业务层;

  • userDAO 属性处添加 @Autowired 注解,表示 IoC 容器自动完成装载,默认是 byType 的方式。

(4)修改 UserDAOImpl

@Repository
public class UserDAOImpl implements UserDAO{

    private static Map<Integer,User> users;

    static{
        users = new HashMap<Integer,User>();
        users.put(1, new User(1, "张三"));
        users.put(2, new User(2, "李四"));
        users.put(3, new User(3, "王五"));
    }

    @Override
    public User getUserById(int id) {
        // TODO Auto-generated method stub
        return users.get(id);
    }

}

做了一处改动:在类名处添加 @Repository 注解,表示该类是数据接口层。

(5)运行测试代码

ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
UserController userController = (UserController) applicationContext.getBean("userController");
User user = userController.getUserById(1);
System.out.println(user);


运行结果如下图所示。

成功,通过结果我们可以得出结论,使用注解的方式可大大简化代码的编写,因此在实际开发中,推荐使用基于注解的方式来架构分层。我们分别给 UserController、UserService、UserDAO 添加了 @Controller、@Service、@Repository 注解。

IoC 中可以给类添加的注解有 4 种:

  • @Controller

  • @Service

  • @Repository

  • @Component

在实际开发中,我们使用 @Controller、@Service、@Repository 分别表示 Controller 层、Service 层、DAO 层。前面提到过,类中属性的自动装载默认是通过 byType 的方式实现的。自动装载除了 byType 的方式,还可以使用 byName,使用 byName 的方式,需要结合 @Qualifier 注解一起使用,具体操作如下所示。

@Controller
public class UserController {

    @Autowired()
    @Qualifier("userService")
    private UserService userService;

    public User getUserById(int id){
        return userService.getUserById(id);
    }
}


我们知道 byName 的方式是通过属性名去匹配对应 bean 的 id 属性值,但是基于注解的方式我们并没有给 bean 设置 id,如何完成呢?

其实在类中添加注解时,已经设置了默认的 id,即类名首字母小写之后的值就是 id 的默认值。

@Service
public class UserServiceImpl implements UserService


此时,IoC 容器中默认赋值,UserService bean 的 id=userService,与 UserController 中的属性名一致,因此可以完成自动。

现在做出修改,手动赋值,设置 UserService bean 的 id=myUserService,如下所示。

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

    @Autowired
    private UserDAO userDAO;

    @Override
    public User getUserById(int id) {
        // TODO Auto-generated method stub
        return userDAO.getUserById(id);
    }

}


很显然,UserController 中的 userService 属性也需要去匹配 name=myUserService 的 bean,因此设置 @Qualifier("myUserService"),如下所示。

@Controller
public class UserController {

    @Autowired()
    @Qualifier("myUserService")
    private UserService userService;

    public User getUserById(int id){
        return userService.getUserById(id);
    }
}

@Qualifier() 中的值必须与 @Service() 中的值一致,才能完成自动装载。

总结

本讲我们讲解了 Spring 基于注解的开发方式,相比于传统的基于 XML 配置文件的方式,基于注解的方式很显然更加方便、快捷,可以提高开发效率,在实际开发中我们也会选择这种方式。

以上是关于Spring IoC 基于注解的开发的主要内容,如果未能解决你的问题,请参考以下文章

Spring源码剖析-基于注解的IOC启动流程

Spring的IOC注解开发入门2

Spring-IOC学习笔记-08基于JavaConfig开发

Spring基于注解的IOC配置

Spring基于注解的IOC配置

基于注解的Ioc配置 —— Spring