一. 前言
在使用Spring之前,我们的业务层依赖数据层,而控制层又依赖业务层,也就是在Service里需要new Dao,而在Servlet中又需要new Service。
有了Spring,我们便可以使用XML或者注解的方式,将Service需要的Dao注入Service或者将Servlet需要的Service注入Servlet,下面以注解的方式为例。
二. 使用SPEL
1. 将applicationContext.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:content="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 https://www.springframework.org/schema/context/spring-context.xsd"> <content:component-scan base-package="io.zhangjia.spring" /> </beans>
2. 将BookService修改为:
package io.zhangjia.spring.service; import io.zhangjia.spring.dao.BookDao; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class BookService { // @Value("bookDao") 不能这么写,会当做String字符串处理 @Value("#{bookDao}") private BookDao bookDao; public BookDao getBookDao() { System.out.println("bookDao = " + bookDao); return bookDao; } public BookService() { System.out.println("BookService.BookService"); } }
注意,这里的@Value注解,不能再使用 @Value(“bookDao”),而需要使用SPEL,SPEL是Spring的表达式语言,可以通过SPEL引用其他Bean、数学运算或者逻辑判断。
@Value(“#{bookDao}”) 意为引用id为bookDao的bean,即BookDao(再次强调一遍,我们并没有手动为BookDao设置ID,但是为其设置了Component注解,所以其默认id即为类名首字母小写:bookDao)
另外,使用注解的方式甚至可以省略setter方法,所以上面的代码中只提供了getter方法用于测试。
3. 将BookController修改为:
package io.zhangjia.spring.controller; import io.zhangjia.spring.service.BookService; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Controller; @Controller("zhangjia") public class BookController { @Value("#{bookService}") private BookService bookService; public BookService getBookService() { System.out.println("bookService = " + bookService); return bookService; } public BookController() { System.out.println("BookController.BookController"); } }
@Controller(“zhangjia”) 代表不再使用bean的默认ID(即类名首字母小写bookController,而是使用zhangjia)
4. 测试类:
public class Test { public static void main(String[] args) { // 初始化Spring的IOC容器 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); BookService bookService = (BookService) context.getBean("bookService"); bookService.getBookDao(); BookController zhangjia = (BookController)context.getBean("zhangjia"); zhangjia.getBookService(); context.close(); } } 输出: bookDao = io.zhangjia.spring.dao.BookDao@59717824 bookService = io.zhangjia.spring.service.BookService@146044d7
四. 使用注解完成属性的自动注入
在《Spring:使用JdbcTemplate开发DAO》一文中,我们通过XML的方式完成了自动注入,除了使用XML的方式还可以使用注解来完成自动注意,还是以上面的例子为例,我们使用注解来完成上述例子中bookService和bookController的自动注入。
使用注解来完成属性的自动注入非常简单,只需要将@Value修改为 @Autowired 即可:
@Service public class BookService { @Autowired private BookDao bookDao; .... } @Controller("zhangjia") public class BookController { @Autowired private BookService bookService; .... }
直接使用@Autowired存在一个问题,以BookController为例,如果我们的项目中没有BookService,则会触发异常,比如我们将BookService的@Service注解删除,此时再运行测试类,则会报以下异常:
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'io.zhangjia.spring.service.BookService' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
我们可以为Autowired设置required属性来选择是否必须注入
-
true:(默认的,注入失败会出现异常)
-
false:不强制注入,注入失败不会有异常
将修改为:
@Controller("zhangjia") public class BookController { @Autowired(required = false) private BookService bookService; ... }
此时再次运行测试类,不会报任何异常
请登录之后再进行评论