• Spring注入


      注入作为Spring最大的武器,已经在java代码中遍地开花。注入的方式也从最原始的set、构造器发展到现在的注解、自动扫描等高科技,为了让大家了解Spring的历史,这里也来聊聊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="cn.hello.millet.EnvConfig">
            <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 EnvConfig(String appname, String env, String hostname){
            this.appname = appname;
            this.type = EnvType.getEnvType(env);
            this.initHostname(hostname);
        }

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

        <bean id="ms.common.msDemoConsumer.consumer" class="cn.hello.newportal.pg.etcd.consumer.DemoPageConsumer"
            init-method="init">
            <constructor-arg index="0" type="cn.hello.millet.MilletContext"
                ref="milletContext" />
            <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="ms.migu.cache" />”即可,这样就能扫描ms.migu.cache包路径下所有的带有@Component、@Repository、@Service或@Controller的类,发现了就注册到IOC容器中。这里需要注意context:component-scan同时具有注册、发现bean的功能,而context:annotation-config只能发现,所以前者包含了后者,如果配置了前者,那就可以不配置后者。

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

    <context:component-scan base-package="ms.hello.cache" />
    package ms.hello.cache;

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

      把MessageDetailServiceImpl改成这样是ok的

    public class MessageDetailServiceImpl
    {
        @Resource
        private GetDetailMsgsMethodImpl getDetailMsgsMethodImpl;
        
        public void init()
        {
            getDetailMsgsMethodImpl.init();
        }
        
    } 

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

    public class MessageDetailServiceImpl
    {
        @Autowired
        @Qualifier("GetDetailMsgsMethodImplB")
        private GetDetailMsgsMethod getDetailMsgsMethod;
        
        public void init()
        {
            getDetailMsgsMethod.init();
        }
        
    } 

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

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

  • 相关阅读:
    Kernel parameter requirements ( Linux DB2)
    db2 backup export
    db2 活动日志激增的原因分析处理
    db2 应用的最常见状态(转)
    db2 reorg到底需要多少表空间(转)
    HDLM for AIX安装
    db lock
    db2 tablespaces table bufferpools reorgs
    AIX文件系统和存储部署(转)
    真正看网络代码
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/7459941.html
Copyright © 2020-2023  润新知