Java for Web学习笔记(五六):Spring框架简介(5)自动识别

标注和自动识别

  在大型的项目中,有数百的beans,无论用xml还是手动代码设置都很崩溃。可以通过自动扫描和标注设置,如servlet中的annotation的标注。

  类标注:@org.springframework.stereotype.Component:可以写@Compoment,表明是Srping管理的beans,Sping将实例化,并注入到他们的依赖。@Controller(可以进一步分为@WebController,@RestController), @Repository,@Service,都是bean。

  方法标注:@org.springframework.beans.factory.annotation.Autowired(在import相关的package,同样可以写为@Autowired),表明应在实例化后注入,也可以在构造函数中标记。一般Spring管理的bean必须有零参数的构造函数,但是在@Autowired构造函数的情况下,将注入所有的构造函数的参数。

java代码中增加标注

@Service

@Service
public class GreetingServiceImpl implements GreetingService{
    @Override
    public String getGreeting(String name) {
        return "Hello," + name + "!";
    }
}

@Controller和@Autowired
  我们可以使用@Inject(javax.inject.Inject)来替代@Autowired。

@Controller
public class HelloController {
    private GreetingService greetingService;

    //表明实例化后,此处马上注入
    @Autowired
    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }
    .......   
}
  我们还可以将@Autowired加在field上

@Controller
public class HelloController {
    @Autowired
    private GreetingService greetingService;

    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }
    .......   
}
  我们还可以将@Autowired加在constructor上

public class HelloController {
    private GreetingService greetingService;

    @Autowired
    public HelloController(GreetingService greetingService){
        this.greetingService = greetingService;
    }
    ... ...
}

上下文的xml配置

rootContext.xml
  使用上一个例子的web.xml,无需更改。rootContext.xml使用到context:,schema所以需要加上context,我们设置通过标注来配置,以及扫描哪个包。

<?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"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.3.xsd">
     <context:annotation-config />
     <context:component-scan base-package="cn.wei.flowingflying.chapter12">
          <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
     </context:component-scan>
</beans>

ServletContext.xml
  看xml的内容,有bean,mvc,context,在schema中要补齐。同样设置通过标注来配置,以及扫描哪个包。

<?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/mvc
           http://www.springframework.org/schema/mvc/spring-mvc-4.3.xsd
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-4.3.xsd">  

       <mvc:annotation-driven />    

       <context:annotation-config />

       <context:component-scan base-package="cn.wei.flowingflying.chapter12" use-default-filters="false">
             <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
       </context:component-scan>
</beans>

exclude和include
  注意到在根上下文的扫描设置context:component-scan中,我们加入了exclude-filter,而在servlet context中则设置了include-filter。如果我们不设置,均采用下面:

<context:component-scan base-package="cn.wei.flowingflying.chapter12" />

  如果这样设置,将扫描所有的@Components。也就是将这个cn.wei.flowingflying.chapter12下面的文件分布在分布扫描了两次,一次在根上下文,一次在dispatcherservlet context,就会有两个HelloController实例和两个GreetingServiceImpl实例。

  我们希望在root context中扫描services, repositories以及其他业务逻辑,而DispacherServlet context只扫描controller。因此在root context中,我们通过exclude-filter设置扫描controller外所有的组件:

<context:component-scan base-package="com.yourcompany.yourproject">
   <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
  在DispatcherServlet context中则通过include-filter要求扫描Controller。use-default-filters为false表示不扫描,缺省为true。下面表示只扫描Controller。

<context:component-scan base-package="com.yourcompany.yourproject" use-default-filters="false">
   <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>

局限

  自动扫描方式很方便,但有局限:

  • 第三方提供的类作为bean:我们无法去增加spring annotation
  • 不能自动注册的bean,例如Java Persistence API。

  在上述情况,我们需要在配置中声明<bean>元素进行补充。

识别或注入错误

  如果spring找不到bean的依赖,或者找到多个依赖,就会在启动是抛出异常。

  对于多个依赖,可以使用@org.springframework.beans.factory.annotation.Qualifier或者@org.springframework.context.annotation.Primary来避免。

Controller指定注入bean名字:@Qualfier

  当使用@Autowired,@Qualifier可以制定bean的名字。我们在例子中增加GreetingServiceImpl2的Service实现

  service bean greeting1:

@Service(value="greeting1")
public class GreetingServiceImpl implements GreetingService{
    ......
}
  service bean greeting2:
@Service(value="greeting2")
public class GreetingServiceImpl2 implements GreetingService{
    ......
}
  controller bean

@Controller
public class HelloController {
    private GreetingService greetingService;

    @Autowired
    @Qualifier("greeting2")
    public void setGreetingService(GreetingService greetingService) {
        this.greetingService = greetingService;
    }
    ... ...
}

bean要求作为@Primary

  service bean 1:

@Service
public class GreetingServiceImpl implements GreetingService{
    ........
}
  service bean 2:

@Service
@Primary
public class GreetingServiceImpl2 implements GreetingService{
    .... ....
}
  Controller bean,将优先使用标记@Primary的bean
@Controller
public class HelloController {
    private GreetingService greetingService;

    @Autowired
    public void setGreetingService(GreetingService greetingService) {
         this.greetingService = greetingService;
    }
}

相关链接: 我的Professional Java for Web Applications相关文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值