在spring中通过Autowired注解巧妙实现策略模式

在最近的一个项目中由于项目需要,需要将代码进行扩展与兼容处理,我在最开始时是通过配置文件的方式去实现的,但代码写着写着就发现对于某些需要配置的地方比较少的话还好处理,但是对于需要灵活变动的地方太多的话写起来就太麻烦了,而且写起来也感觉比较容易出错,于是考虑到了是否可以用JAVA的策略模式去实现呢?

带着这样的想法,便在网上搜了下spring框架与策略模式相关的信息,看了后发现还真有这样的文章,见https://blog.csdn.net/u011659172/article/details/79140561Spring 实现策略模式,在公司里便通过文章的写法快速完成了开发,但对于有一处Autowired的用法我之前还没有那样写过,晚上下班回来后原来研究下spring对于那块处理的源码,但时间比较仓促,源码就先不去研究了,就了解下Autowired的那种用法吧。

先附上如下的代码:

public interface TalkService {
    void talk(String content);
}
@Service(value = "withSisterTalkService")
public class WithSisterTalkService implements TalkService {
    @Override
    public void talk(String content) {
        System.out.println(this.getClass().getName() + ":" + content);
    }
}
@Service(value = "withGirlFriendTalkService")
public class WithGirlFriendTalkService implements TalkService {
    @Override
    public void talk(String content) {
        System.out.println(this.getClass().getName() + ":" + content);
    }
}
@Service
public class TalkServiceStrategyContext implements TalkService {

    private Map<String, TalkService> strategyMap = new ConcurrentHashMap<>();

    @Autowired
    public TalkServiceStrategyContext(Map<String, TalkService> strategyMap) {
        this.strategyMap.clear();
        this.strategyMap.putAll(strategyMap);
    }

    @Override
    public void talk(String content) {

    }
}
    @Autowired
    private Map<String, TalkService> talkServiceMap;

    @GetMapping(value = "doTest")
    public String doTest() {
        Set<String> strings = talkServiceMap.keySet();
        for (String string : strings) {
            System.out.println(string + ":" + talkServiceMap.get(string).toString());
        }
        return this.getClass().getName();
    }

其访问测试controller后,打印的信息如下:

talkServiceStrategyContext:com.haiyang.onlinejava.complier.service.impl.TalkServiceStrategyContext@2f0b1419
withGirlFriendTalkService:com.haiyang.onlinejava.complier.service.impl.WithGirlFriendTalkService@1cf19a02
withSisterTalkService:com.haiyang.onlinejava.complier.service.impl.WithSisterTalkService@1ef3c76d

看了后感觉很奇怪,在上方只定义了一个map<String,TalkService>的map,居然它就能自动找到实现了TalkService的所有bean,并将service的beanName作为了key,感觉还是牛逼啊,spring的注解居然还能这样用。

然后简单看了下Autowired的源码,其javaDoc文档里也有说明:

package org.springframework.beans.factory.annotation;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Marks a constructor, field, setter method or config method as to be
 * autowired by Spring's dependency injection facilities.
 *
 * <p>Only one constructor (at max) of any given bean class may carry this
 * annotation, indicating the constructor to autowire when used as a Spring
 * bean. Such a constructor does not have to be public.
 *
 * <p>Fields are injected right after construction of a bean, before any
 * config methods are invoked. Such a config field does not have to be public.
 *
 * <p>Config methods may have an arbitrary name and any number of arguments;
 * each of those arguments will be autowired with a matching bean in the
 * Spring container. Bean property setter methods are effectively just
 * a special case of such a general config method. Such config methods
 * do not have to be public.
 *
 * <p>In the case of multiple argument methods, the 'required' parameter is
 * applicable for all arguments.
 *
 * <p>In case of a {@link java.util.Collection} or {@link java.util.Map}
 * dependency type, the container will autowire all beans matching the
 * declared value type. In case of a Map, the keys must be declared as
 * type String and will be resolved to the corresponding bean names.
 *
 * <p>Note that actual injection is performed through a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} which in turn means that you <em>cannot</em>
 * use {@code @Autowired} to inject references into
 * {@link org.springframework.beans.factory.config.BeanPostProcessor
 * BeanPostProcessor} or
 * {@link org.springframework.beans.factory.config.BeanFactoryPostProcessor BeanFactoryPostProcessor}
 * types. Please consult the javadoc for the {@link AutowiredAnnotationBeanPostProcessor}
 * class (which, by default, checks for the presence of this annotation).
 *
 * @author Juergen Hoeller
 * @author Mark Fisher
 * @since 2.5
 * @see AutowiredAnnotationBeanPostProcessor
 * @see Qualifier
 * @see Value
 */
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {

	/**
	 * Declares whether the annotated dependency is required.
	 * <p>Defaults to {@code true}.
	 */
	boolean required() default true;

}

关注这句:

In case of a java.util.Collection or java.util.Map dependency type, the container will autowire all beans matching the declared value type. In case of a Map, the keys must be declared as type String and will be resolved to the corresponding bean names.

它大致是说Autowired当使用在Collection里时,会将所申明类的所有实现类都放在那个指定的Collection里;

如果Autowired和map使用的话呢,它将它bean的名称作为key,所有的bean作为value.

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水中加点糖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值