• 中文
    • English
  • 注册
  • 查看作者
  • Spring:使用SPEL以及使用注解完成属性的自动注入

    一.  前言

    在使用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;
        ...
     }

    此时再次运行测试类,不会报任何异常


  • 0
  • 0
  • 0
  • 4.1k
  • 请登录之后再进行评论

    登录
    单栏布局 侧栏位置: