18.4 应用@Autowired和@Service进行依赖注入

18.4 应用@Autowired和@Service进行依赖注入

使用Spring框架的一个好处是容易进行依赖注入。毕竟,Spring框架一开始就是一个依赖注入容器。将依赖注入到Spring MVC控制器的最简单方法是通过注解@Autowired到字段或方法Autowired注解类型属于org.springframework.beans.factory.annotation包。
此外,**为了能被作为依赖注入,类必须要注明为@Service**。该类型是org.springframework.stereotype包的成员。Service注解类型指示类是一个服务。此外,在配置文件中,还需要添加一个<component-scan/>元素来扫描依赖基本包:

1
<context:component-scan base-package="dependencyPackage"/>

下面以app18b应用进一步说明Spring MVC如何应用依赖注入。在app18b应用程序中,ProductController类已经不同于app18a

app18b的ProductController类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package app18b.controller;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import app18b.domain.Product;
import app18b.form.ProductForm;
import app18b.service.ProductService;
@Controller
public class ProductController
{
private static final Log logger = LogFactory
.getLog(ProductController.class);
@Autowired
private ProductService productService;
@RequestMapping(value = "/product_input")
public String inputProduct()
{
logger.info("inputProduct called");
return "ProductForm";
}
@RequestMapping(
value = "/product_save",
method = RequestMethod.POST
)
public String saveProduct(ProductForm productForm,
RedirectAttributes redirectAttributes)
{
logger.info("saveProduct called");
// no need to create and instantiate a ProductForm
// create Product
Product product = new Product();
product.setName(productForm.getName());
product.setDescription(productForm.getDescription());
try
{
product
.setPrice(Float.parseFloat(productForm.getPrice()));
} catch (NumberFormatException e)
{}
// add product
Product savedProduct = productService.add(product);
redirectAttributes.addFlashAttribute("message",
"The product was successfully added.");
return "redirect:/product_view/" + savedProduct.getId();
}
@RequestMapping(value = "/product_view/{id}")
public String viewProduct(@PathVariable
Long id,Model model)
{
Product product = productService.get(id);
model.addAttribute("product", product);
return "ProductView";
}
}

app18a中相比,app18b中的ProductController类做了一系列的调整。首先是在如下的私有字段上增加了@Autowired注解

1
2
@Autowired
private ProductService productService

ProductService是一个提供各种处理产品方法的接口。productService字段添加@Autowired注解会使ProductService的一个实例被注入到ProductController实例中
下面代码分别显示了ProductService接口及其实现类ProductServiceImpl。注意,**为了使类能被Spring扫描到,必须为其标注@Service**。

ProductService接口

1
2
3
4
5
6
7
package app18b.service;
import app18b.domain.Product;
public interface ProductService
{
Product add(Product product);
Product get(long id);
}

ProductServiceImpl类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package app18b.service;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import org.springframework.stereotype.Service;
import app18b.domain.Product;
@Service
public class ProductServiceImpl
implements
ProductService
{
private Map<Long,Product> products = new HashMap<Long,Product>();
private AtomicLong generator = new AtomicLong();
public ProductServiceImpl()
{
Product product = new Product();
product.setName("JX1 Power Drill");
product.setDescription(
"Powerful hand drill, made to perfection");
product.setPrice(129.99F);
add(product);
}
@Override
public Product add(Product product)
{
long newId = generator.incrementAndGet();
product.setId(newId);
products.put(newId, product);
return product;
}
@Override
public Product get(long id)
{
return products.get(id);
}
}

Spring MVC配置文件

app18bSpring MVC配置文件中有两个<component-scan/>元素;一个用于扫描控制器类,另一个用于扫描服务类。

SpringMVC配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?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:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!-- 扫描控制器 -->
<context:component-scan
base-package="app18b.controller" />
<!-- 扫描服务 -->
<context:component-scan
base-package="app18b.service" />
<mvc:annotation-driven />
<mvc:resources mapping="/css/**" location="/css/" />
<mvc:resources mapping="/*.html" location="/" />
<!-- 视图解析器 -->
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsp/" />
<property name="suffix" value=".jsp" />
</bean>
</beans>