SpringMVC实现依赖注入的几个常用注解的用法解释和示例说明

在以前,我们使用Spring对一些属性进行依赖注入(DI)时,通常都是通过在配置文件中配置一个个的<bean>标签来实现,比如说这样:

<bean id="userBiz" class="cn.zifangsky.biz.UserBizImpl">
	<property name="userDAO" ref="userDAO"/>
</bean>

但是一旦项目大了之后,如果要把所有的这些依赖关系都在配置文件中配置的话,无疑逻辑上是非常混乱的,这时我们就可以考虑使用几个常用的注解来实现依赖关系的注入。

实现依赖注入的几个常用注解分别是:

  • @Component 是所有受Spring 管理组件的通用形式,但是不推荐使用
  • @Repository 对应数据访问层的Bean
  • @Service 对应业务层的Bean
  • @Controller 对应控制层的Bean

除了这几个对类的注解外,还有几个对类中属性的注解,主要目的是告诉Spring这个属性应该用那个前面已经注解过的类来实例化,它们分别是:

  • @Resource 默认按名称来装配注入,只有当找不到与名称相匹配的bean时才会按照类型来装配注入
  • @Autowired 默认按类型来装配注入,如果想按照名称来装配注入,则需要结合@Qualifier一起使用
  • @Qualifier 默认按名称来装配注入

由于@Autowired是按照类型来注入的,因此当同类型的变量有多个需要注入时,仅仅使用@Autowired就会出现问题,这时可以结合@Qualifier来使用,比如:

@Autowired
@Qualifier("userDaoImpl")
private UserDao userDao;

当然,由于@Resource这个注解有另外两个注解都有的功能,同时@Resource这个注解是基于J2EE的,而@Autowired和@Qualifier是属于Spring的,所以我们最好使用@Resource进行依赖注入,有利于减小应用与Spring的耦合

对于上面提到的这些注解的一些具体用法,接下来我将以一个具体的实例来举例说明:

一 测试环境的搭建

1 项目结构与相关jar包:

 

2 web.xml以及springmvc-servlet.xml:

i)web.xml:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
	  http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

	<servlet>
		<servlet-name>springmvc</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>springmvc</servlet-name>
		<url-pattern>*.html</url-pattern>
	</servlet-mapping>

	<filter>
		<filter-name>characterEncodingFilter</filter-name>
		<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
		<init-param>
			<param-name>encoding</param-name>
			<param-value>UTF-8</param-value>
		</init-param>
	</filter>
	<filter-mapping>
		<filter-name>characterEncodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

</web-app>

ii)springmvc-servlet.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"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
       					   http://www.springframework.org/schema/beans/spring-beans-4.0.xsd 
       					   http://www.springframework.org/schema/context
       					   http://www.springframework.org/schema/context/spring-context-4.0.xsd
       					   http://www.springframework.org/schema/mvc 
       					   http://www.springframework.org/schema/mvc/spring-mvc-4.0.xsd">

	<context:component-scan base-package="cn.zifangsky.dao" />
	<context:component-scan base-package="cn.zifangsky.service" />
	<context:component-scan base-package="cn.zifangsky.controller" />
	<!-- <context:component-scan base-package="cn.zifangsky.* *.controller" /> -->

	<context:annotation-config />  <!-- 激活Bean中定义的注解 -->
    <mvc:annotation-driven /> 

	<bean
		class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/pages/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

可以看出,在上面的配置文件中定义了三个“context:component-scan”标签分别用于扫描数据访问层、业务层以及控制层的注解,其他配置不用多说

二 注解的使用实例

1 首先是model层的User.java:

package cn.zifangsky.model;

public class User {
	private String name;
	private String password;

	public String getName() {
		return name;
	}

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

	public String getPassword() {
		return password;
	}

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

}

这一层只是简单定义了一个“User”模型,并没有使用到任何注解

2 数据访问层的UserDao.java和UserDaoImpl.java:

i)UserDao.java:

package cn.zifangsky.dao;

import cn.zifangsky.model.User;

public interface UserDao {
	/**
	 * 校验登录信息
	 * */
	public String check(User u);
}

ii)UserDaoImpl.java:

package cn.zifangsky.dao.impl;

import org.springframework.stereotype.Repository;

import cn.zifangsky.dao.UserDao;
import cn.zifangsky.model.User;

@Repository("userDaoImpl")
public class UserDaoImpl implements UserDao {

	public String check(User u) {
		//这里只是简单判断是否为空,实际需要查询数据库等操作
		if(u != null){
			System.out.println("登录的用户信息是:");
			System.out.println("--|用户名:" + u.getName());
			System.out.println("--|密码:" + u.getPassword());
		}

		return "ok";
	}

}

可以看出,在上面的代码中我们在类上定义了一个@Repository注解,用于表示这个类是数据访问层的,同时给它起了个名字叫“userDaoImpl”。问:为什么在实现类上添加@Repository注解而不是在UserDao接口上添加注解?

其实这个问题只要想一下我们在配置文件中使用<bean>标签是如何配置的就清楚了,比如对于这样一个bean:

<bean id="userDAO" class="cn.zifangsky.dao.UserDAOImpl">
	<property name="sessionFactory" ref="sessionFactory" />
</bean>

我们可以发现,“class”属性这里指向的是一个具体的实现类而不是它的接口。原因很简单,我们需要的是一个具体的类来实例化或者说在其他类中也需要这样一个具体的类来进行参数注入,显然这是不能使用接口的。因此,上面为何在一个实现类上添加注解也是基于同样的道理,不信可以试试把@Repository注解从UserDaoImpl转移到UserDao这个接口上,看看项目运行时会不会报错?

3 业务逻辑层UserService.java和UserServiceImpl.java:

i)UserService.java:

package cn.zifangsky.service;

import cn.zifangsky.model.User;

public interface UserService {
	/**
	 * 模拟登录
	 * */
	public String login(User u);
}

ii)UserServiceImpl.java:

package cn.zifangsky.service.impl;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cn.zifangsky.dao.UserDao;
import cn.zifangsky.model.User;
import cn.zifangsky.service.UserService;

@Service("userServiceImpl")
public class UserServiceImpl implements UserService {
	@Resource(name = "userDaoImpl")
	private UserDao userDao;

//	public void setUserDao(UserDao userDao) {
//		this.userDao = userDao;
//	}

	public String login(User u) {
		return userDao.check(u);
	}
}

在这里,UserServiceImpl这个类上面定义了一个@Service注解,表示它是业务逻辑层上的一个类,同样给它起了一个名字叫“userServiceImpl”。通过上面的代码可以看到,我们给userDao这个属性定义了一个@Resource注解,通过一个“name”属性表示引用的是一个名为“userDaoImpl”的UserDao类型的类来实例化userDao属性,毫无疑问这里指的就是上面定义了“@Repository(“userDaoImpl”)”注解的UserDaoImpl.java了

注:给属性添加了注解之后是可以不用再写对应的setter方法的

4 控制层UserController.java:

package cn.zifangsky.controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

import cn.zifangsky.model.User;
import cn.zifangsky.service.UserService;

@Controller
public class UserController {
	@Resource(name="userServiceImpl")
	private UserService userService;

	@RequestMapping(value="/analogLogin")
	public String user(@RequestParam(name="name",required=false) String name,@RequestParam(name="password",required=false) String password){
		User user = new User();
		user.setName(name);
		user.setPassword(password);

		String result = userService.login(user);
		System.out.println(result);

		return "success";
	}

}

@Controller注解的含义这里就不用多说了,跟上面的@Repository和@Service类似。通过定义的@RequestMapping注解我们在访问“http://localhost:[port]/AnnotationDemo/analogLogin.html”就可以转到user这个方法进行处理。而@RequestParam注解则是用来获取请求中的参数用的

三 测试

在浏览器中访问:http://localhost:8090/AnnotationDemo/analogLogin.html?name=haha&password=123qwe

对应的输出如下:

登录的用户信息是:
--|用户名:haha
--|密码:123qwe
ok

如果出现上面的控制台输出则表明注解已经配置正确了

时间: 2024-08-05 14:13:38

SpringMVC实现依赖注入的几个常用注解的用法解释和示例说明的相关文章

框架 day36 Spring3 入门,DI依赖注入,装配bean基于xml/注解, 整合Junit4,配置约束自动提示

1 什么是spring 1.1官网 spring.io 1.2介绍 Spring的核心是控制反转(IoC)和面向切面(AOP). IoC(Inverse of Control 反转控制) AOP(Aspect Oriented Programming 面向切面编程为内核) 简单来说,Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架. *轻量级:依赖其他内容较小,使用资源消耗也少.对比:EJB 重量级 *分层:经典三层体系架构,spring 提供解决方案

spring四种依赖注入方式 (set,构造器,工厂,注解 )

平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是"控制反转",通俗的理解是:平常我们new一个实例,这个实例的控制权是我们程序员,而控制反转是指new实例工作不由我们程序员来做而是交给spring容器来做. spring有多种

Spring 依赖注入(DI)的注解

Spring中想要使用注解进行依赖注入,需要进行如下配置: <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:schemaLocatio

SpringMVC常用注解的用法

1. @PathVariable 当使用@RequestMapping URI template 样式映射时, 即 someUrl/{paramId}, 这时的paramId可通过 @Pathvariable注解绑定它传过来的值到方法的参数上.示例代码: @Controller @RequestMapping("/owners/{ownerId}") public class RelativePathUriTemplateController { @RequestMapping(&qu

Android依赖注入之BufferKnife 8.0注解使用

前言: App项目开发大部分时候还是以UI页面为主,这时我们需要调用大量的findViewById以及setOnClickListener等代码,控件的少的时候我们还能接受,控件多起来有时候就会有一种想砸键盘的冲动.所以这个时候我们想着可以借助注解的方式让我们从这种繁重的工作中脱离出来,也让代码变得更加简洁,便于维护,今天主要学习一下只专注View.Resource.Action注解框架BufferKnife . BufferKnife 介绍 BufferKnife 是一个专注于Android系

AngularJs学习笔记6——四大特性之依赖注入

压缩工具:YUI-compressor 为了优化网页功能,对一些脚本文件进行压缩,比如:删除所有的注释和空格等,简化形参.但是AngularJs模块中可以声明多种组件,如控制器.指令.过滤器.服务等.创建这些模块组件对象时,构造函数是由AngularJS调用的,故不能像普通函数那样,声明任意的形参.使得压缩后的文件无法使用,这时候采用标记式和行内式的数组形式(注意顺序的对应关系),使得压缩后依然可以使用. 依赖:实现功能的时候,如果需要某些模块,模块就是需要的依赖 AngularJS会自动根据依

Spring学习一(依赖注入/Bean/注解等)

1.Spring依赖注入的方式. 2.依赖注入的类型 3.Bean的作用域 4.自动注入 5.使用注解的方式 6.在spring配置文件中引入属性文件 1.Spring依赖注入的方式 平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理. spring提出了依赖注入的思想,即依赖类不由程序员实例化,而是通过spring容器帮我们new指定实例并且将实例注入到需要该对象的类中.依赖注入的另一种说法是“

ASP.NET Core中使用自定义MVC过滤器属性的依赖注入

原文:ASP.NET Core中使用自定义MVC过滤器属性的依赖注入 除了将自己的中间件添加到ASP.NET MVC Core应用程序管道之外,您还可以使用自定义MVC过滤器属性来控制响应,并有选择地将它们应用于整个控制器或控制器操作. ASP.NET Core中常用的MVC过滤器之一是  ExceptionFilterAttribute,用于处理Wep API应用程序中的错误响应.它很容易实现,开发人员和我在ASP.NET Core中使用MVC过滤器属性所面临的问题是访问Startup.cs类

开涛spring3(12.2) - 零配置 之 12.2 注解实现Bean依赖注入

12.2  注解实现Bean依赖注入 12.2.1  概述 注解实现Bean配置主要用来进行如依赖注入.生命周期回调方法定义等,不能消除XML文件中的Bean元数据定义,且基于XML配置中的依赖注入的数据将覆盖基于注解配置中的依赖注入的数据. Spring3的基于注解实现Bean依赖注入支持如下三种注解: Spring自带依赖注入注解: Spring自带的一套依赖注入注解: JSR-250注解:Java平台的公共注解,是Java EE 5规范之一,在JDK6中默认包含这些注解,从Spring2.