Spring注入

  注入作为Spring最强大的武器,已经在java代码中遍地开花。注入的方式也从最原始的set、构造器等鸟枪发展到现在的注解、自动扫描等高科技大炮了。这里也来聊聊IOC。

  (1)首先是set注入,需要做两件事:配置property,实现set方法,代码如下

    <bean class="com.alibaba.dubbo.demo.consumer.DemoAction" init-method="start">        
        <property name="anotherUserRestService" ref="anotherUserRestService" />
    </bean>
public class DemoAction {

    private AnotherUserRestService anotherUserRestService;

public void setAnotherUserRestService(AnotherUserRestService anotherUserRestService) { this.anotherUserRestService = anotherUserRestService; } public void start() throws Exception { User user = new User(1L, "larrypage"); System.out.println("SUCCESS: registered user with id " + anotherUserRestService.registerUser(user).getId()); System.out.println("SUCCESS: got user " + anotherUserRestService.getUser(1L)); } }

  这里要注意set后面带的名称,需要与property的name属性anotherUserRestService保持一致,也就是setXXX的XXX必须是配置文件中property的name值。

 

  (2)构造器注入也只要做两件事:配置constructor-arg,实现构造器,看代码

<bean id="envConfig" class="com.hello.WlfConfig">
        <constructor-arg type="java.lang.String" value="${app.name}" />
        <constructor-arg type="java.lang.String" value="${app.env}" />
        <constructor-arg type="java.lang.String" value="${hostname}" />
</bean>
public WlfConfig(String appname, String env, String hostname){
        this.appname = appname;
        this.type = EnvType.getEnvType(env);
        this.initHostname(hostname);
    }

  构造器注入还发展出了索引技术,利用index而不是type来区分构造器入参,如下

    <bean id="wlf.hello.demoConsumer.consumer" class="wlf.hello.consumer.DemoConsumer"
        init-method="init">
        <constructor-arg index="0" type="com.hello.HelloContext"
            ref="helloContext" />
        <constructor-arg index="1" value="${version}" />
    </bean>

 

  (3)静态或者实例工厂的方法注入不常见,不过原理都是相同的,重点是后面的“方法”,也就是bean的注入是从“方法”调用来获取的,这里不举例,具体可以参见使用Spring的StingUtils的commaDelimitedListToStringArray来获取字符串数组

 

  (4)注解注入有@Autowired、@Resource、@Component、@Repository、@Service、@Controller,其中最常用的就是@Autowired,使用它有两个前提:一个是必须支持注解,另一个就是被注入的是IOC里的bean,看代码

<context:annotation-config />

<bean id="zoneResourceService"
  class="com.hello.zoneresource.provider.dao.ZoneResourceServiceImpl" />
public class MobileZoneResourceServiceImpl implements MobileZoneResourceService
{
    @Autowired
    private ZoneResourceService zoneResourceService;
   
    public List<Map<String, Object>> queryCityList(String param)
    {
        BpmUserInfo userinfo = (BpmUserInfo)JsonUtil.getObject4JsonString(param, BpmUserInfo.class);
        List<Map<String, Object>> cityList = zoneResourceService.queryCityList(userinfo);
        return cityList;
    }
}

  上面是在配置文件中加的“<context:annotation-config />”就是为了获取注解的能力,有了@Autowired,zoneResourceService这个bean无需再通过set或者构造器注入。我们也可以通过@Component、@Repository、@Service或@Controller来注入bean到IOC,然后通过@Autowired来引入这个bean。只不过为了能够发现那4个注解,这时需要获取自动扫描的能力。

  把“<context:annotation-config />”改为“<context:component-scan base-package="com.wlf.hello" />”即可,这样就能扫描com.wlf.hello包路径下所有的带有@Component、@Repository、@Service或@Controller的类,发现了就注册到IOC容器中。这里需要注意context:component-scan同时具有注册、发现bean的功能,而context:annotation-config只能发现,所以前者包含了后者,如果配置了前者,那就可以不配置后者。

  @Resource跟@Autowired差不多的作用,也是用来引入bean,只不过它默认是根据名称来,而@Autowired是根据对象类型来。看代码

<context:component-scan base-package="com.wlf.hello" />
package com.wlf.hello;

@Service
public class GetHelloMethodImpl
{
public void init()
    {
        super.initialize(GetDetailMsgsMethodImpl.class);
    }
}
public class MessageDetailServiceImpl
{
    @Autowired
    private GetHelloMethodImpl getHelloMethodImpl;
    
    public void init()
    {
        getHelloMethodImpl.init();
    }
    
}    

  把MessageDetailServiceImpl改成这样是ok的

public class MessageDetailServiceImpl
{
    @Resource
    private GetHelloMethodImpl getHelloMethodImpl;
    
    public void init()
    {
        getHelloMethodImpl.init();
    }
    
} 

  上面的例子里没有指定具体value值,那么@Service默认使用@Service(value="getHelloMethodImpl")进行bean注册,而@Resource默认按@Resource(name="getHelloMethodImpl")来注入。如果注入的是接口,而实现类有多个,那么@Autowired需要用到@Qualifier注解来区分实现类的类名。假如GetHelloMethodImpl是个接口,实现类有GetHelloMethodImplA和GetHelloMethodImplB,那在注入接口时必须要指明实现类的名称

 

public class MessageDetailServiceImpl
{
    @Autowired
    @Qualifier("GetHelloMethodImplB")
    private GetHelloMethod getHelloMethod;
    
    public void init()
    {
        getHelloMethod.init();
    }
    
} 

 

  上面代码还有一个前提,就是GetDetailMsgsMethodImplB必须也注册到IOC中才能使用@Qualifier引入bean的名称。

 

  @Component是通用注解,标注了它的类都会被注册到IOC容器,而@Repository适用于DAO层,@Service适用于业务层,@Controller适用于web层。但如果使用@Controller不仅仅只是为了注册到IOC,还想作为Spring MVC的controller用于分发web请求的话,那么还需要配置mvn驱动<mvc:annotation-driven />。

posted on 2017-08-31 18:44  不想下火车的人  阅读(222)  评论(0编辑  收藏  举报

导航