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"); Product product = new Product(); product.setName(productForm.getName()); product.setDescription(productForm.getDescription()); try { product .setPrice(Float.parseFloat(productForm.getPrice())); } catch (NumberFormatException e) {} 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配置文件
app18b
的Spring 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>
|