Spring入门(Bean装配,Autowired注解)

@Required

@required注解适用于bean属性的setter方法。
这个注解仅仅表示,受影响的bean属性必须在配置时被填充,通过在bean定义或通过自动装配一个明确的属性值。(也就是说bean的属性必须在配置的时候就被赋值)

public class SimpleMovieLister{

    private MovieFinder movieFinder;

    @Required
    public void setMovieFinder(MovieFinder movieFinder){
        this.movieFinder=movieFinder;
    }

    //...
}

@Required注解并不常用。

@Autowired

Autowired可以理解为自动的进行装配。
1.可以将@Autowired注解为“传统”的setter方法

private MovieFinder movieFinder;

@Autowired
public void setMovieFinder(MovieFinder movieFinder){
    this.movieFinder=movieFinder;
}

2.可用于构造器或成员变量(比@Required范围更广)

@Autowired
private MovieCatalog movieCatalog;

private CustomerPreferenceDao customerPreferenceDao;

@Autowired
public MovieFinder(CustomerPreferenceDao customerPreferenceDao){
    this.customerPreferenceDao=customerPreferenceDao;
}

默认情况下,如果因找不到合适的bean将会导致autowiring失败抛出异常(@Autowired是byType来查找bean,如果没有对应class的bean就会出问题。),可以通过下面的方式避免

public class SimpleMovieLister{

    private MovieFinder movieFinder;

    @Required(required=false)
    public void setMovieFinder(MovieFinder movieFinder){
        this.movieFinder=movieFinder;
    }

    //...
}

设置required=false表示这并不是一个必须的,如果找不到movieFinder这样的bean的实例也可以。

每个类只能有一个构造器被标记为required-true。要知道一个类可以有很多构造器,每个构造器都可以使用@Autowired注解,但是能声明required=true的只有一个。

@Autowired的必要属性,建议使用@Required注解来代替。

例子
之前的InjectionDAOImpl和InjectionServiceImpl可以再次被用到。
给InjectionDAOImpl加上@Repository,InjectionServiceImpl加上@Service,分别对应存储层和业务层

@Repository
public class InjectionDAOImpl implements InjectionDAO {

    public void save(String arg) {
        //模拟数据库保存操作
        System.out.println("保存数据:" + arg);
    }
}
@Service
public class InjectionServiceImpl implements InjectionService {

//  @Autowired
    private InjectionDAO injectionDAO;

    @Autowired
    public InjectionServiceImpl(InjectionDAO injectionDAO) {
        this.injectionDAO = injectionDAO;
    }

//  @Autowired
    public void setInjectionDAO(InjectionDAO injectionDAO) {
        this.injectionDAO = injectionDAO;
    }

    public void save(String arg) {
        //模拟业务操作
        System.out.println("Service接收参数:" + arg);
        arg = arg + ":" + this.hashCode();
        injectionDAO.save(arg);
    }
}

配置文件不变,依然扫描com.imooc.beanannotation这个包。

在InjectionServiceImpl 这里第一个@Autowired用于成员变量。

单元测试类中测试方法代码如下:

@Test
public void testAutowired() {
    InjectionService service = super.getBean("injectionServiceImpl");
    service.save("This is autowired.");
}

前边的@Service并没有显式的指定name,所以这个bean的id为injectionServiceImpl,首字母小写。然后的输出和Service中对应的save方法一致。如下:
Service接受参数:This is autowired.
保存数据:This is autowired.:1728997654

第一行是Service中的输出,第二行是Service中的save方法调用了DAO中的输出,所以这种方式注入是可以的。

第二个@Autowired是构造器方式,在构造器里为成员变量进行赋值,输出和前边一致。

@Autowired
    public InjectionServiceImpl(InjectionDAO injectionDAO) {
        this.injectionDAO = injectionDAO;
    }

第三个是为DAO生成一个set方法,然后加上@Autowired,输出接一样。

也就是说我们通过@Autowired完成了set注入和构造注入,这个直接放在成员变量上和set注入是类似的。

依然是@Autowired

可以使用@Autowired注解那些众所周知的解析依赖性接口(我们可以使用它来注解很多Spring直接的解析依赖性接口,这些主要是解析xml文件或者注解等),比如:BeanFactory,ApplicationContext,Environment,ResourceLoader,ApplicationEventPublisher,and MessageSource。

举例

public class MovieRecommender{

    @Autowired
    private ApplicationContext context;

    public MovieRecommender(){}
    //...
}

我们在当前类里边声明对ApplicationContext的引用,然后使用@Autowired的注解,这时候我们就可以在当前类中得到IOC的上下文信息,然后使用上下文信息。


新的用法,可以通过添加注解给需要该类型的数组的字段或者方法(也就是说可以注解在数组上,所谓的数组就是用Set<>或者List<>),以提供ApplicationContext中的所有特定类型bean(当Set中声明这种类型的时候,当前的ApplicationContext中所有是Set<>中声明类型的bean或者是它的子类都可以被@Autowired注解,并且把这些bean的实例放到当前的集合中去)。

private Set<MovieCatalog> movieCatalogs;

@Autowired
public void setMovieCatalogs(Set<MovieCatalog> movieCatalogs){
    this.movieCatalogs=movieCatalogs;
}

当然也可以用Map(key,value的形式,key是所有bean的id,value是所有bean的对象),即可用于装配key为String的Map。

private Map<String,MovieCatalog> movieCatalogs;

@Autowired
public void setMovieCatalogs(Map<String,MovieCatalog> movieCatalogs){
    this.movieCatalogs=movieCatalogs;
}

同时,如果我们希望数组(bean的实例)是有序的,可以让bean实现org.springframework.core.Ordered接口或使用@Order注解。

注意
@Autowired是由Spring BeanPostProcessor处理的,所以不能再自己的BeanPostProcessor或BeanFactoryPostProcessor类型应用这些注解,后边这些自定义的类型必须通过XML或者Spring的@Bean注解加载。

例子,数组及Map的自动注入
首先定义一个接口BeanInterface
里边没有任何东西

public interface BeanInterface {

}

然后定义BeanInterface的实现BeanImplOne和BeanImplTwo,都使用@Component注解以便能够让Spring容器发现。

@Order(2)
@Component
public class BeanImplOne implements BeanInterface {

}
@Order(1)
@Component
public class BeanImplTwo implements BeanInterface {

}

测试类中定义了测试方法:

@Test
    public void testMultiBean() {
    BeanInvoker invoker = super.getBean("beanInvoker");
    invoker.say();
}

然后定义一个调用类BeanIncoker,也用@Component去注解,先给代码然后解释这个调用类:

@Component
public class BeanInvoker {

    @Autowired
    private List<BeanInterface> list;

    @Autowired
    private Map<String, BeanInterface> map;

    public void say() {
        if (null != list && 0 != list.size()) {
            System.out.println("list...");
            for (BeanInterface bean : list) {
                System.out.println(bean.getClass().getName());
            }
        } else {
            System.out.println("List<BeanInterface> list is null !!!!!!!!!!");
        }

        System.out.println();

        if (null != map && 0 != map.size()) {
            System.out.println("map...");
            for (Map.Entry<String, BeanInterface> entry : map.entrySet()) {
                System.out.println(entry.getKey() + "      " + entry.getValue().getClass().getName());
            }
        } else {
            System.out.println("Map<String, BeanInterface> map is null !!!!!!!!!!");
        }

    }
}

List<>声明数组类型BeanInterface,然后用@Autowired注解当前的变量list。正常情况下,这个list里面会被注解进来Bean的实例,严格上讲就是BeanInterface的两个直接类BeanImplOne和BeanImplTwo。

然后我们定义一个方法say看看输出里边有哪些类。循环list,将list中的每一个bean的名称打出来。
发现两个类One和Two都可以被打印出来,说明@Autowired注解确实可以完成把BeanInterface的两个实现类注解到list当中去。
然后试一试Map,注意Map的key值一定是String,输出的结果差不多。

有一点差别,虽然使用@Autowired会将BeanInterface的所有子类在IOC容器中对应的Bean的实例都放到map和list中去。但是放到list中时只是把对象放进来,放到map中时则是将bean的id和实例一起放进来。

为了实现有序,可以在两个类中写上注解@Order,@Order(value=1)可以写为@Order(1)。分别设置1和2,遍历时候list的顺序根据我们设置的顺序来显示,map则无效。因为对于数组我们经常根据顺序来取,但是map则是依靠key。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值