Spring-Annotation-based-Container-Configuration


title: Spring-Annotation-based-Container-Configuration
date: 2019-01-23 13:58:34
tags: Spring
categories: Spring


注解形式与XML形式注入Bean哪个更好

答案是: 取决于具体情况

注解形式: 更加方便,短的申明,但是需要侵入代码

XML形式: 不用触碰源代码,不用重新编译他们

Spring两者都支持,也可以混合使用没有问题

在Spring2.0中引入了@Required注解,在Spring2.5中引入了@Autoqired注解,同时添加了JSR-250注解@PostConstruct@PreDestroy。Spring3中添加了支持JSR-330javax.inject包中的注解,例如:@Inject@Named

注解在XML配置之前执行,XML的配置能覆盖注解形式的配置

@Required

@Required用来设置Bean的属性,设置该属性为必须项

public class SimpleMovieLister {

    private MovieFinder movieFinder;

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

    // ...
}

但是该注解在Spring 5.1中过期了,更常用的是构造注入

@Autowired

JSR 330中的@Inject注解能够替带@AUtowired注解

可以将@Autowired应用在构造函数上

public class MovieRecommender {

    private final CustomerPreferenceDao customerPreferenceDao;

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

    // ...
}

Fine-tuning Annotation-based Autowiring with @Primary

自动装配有时会导致多个候选,我们可以 使用@Primary来申明装配哪一个

@Configuration
public class MovieConfiguration {

    @Bean
    @Primary
    public MovieCatalog firstMovieCatalog() { ... }

    @Bean
    public MovieCatalog secondMovieCatalog() { ... }

    // ...
}
public class MovieRecommender {

    @Autowired
    private MovieCatalog movieCatalog;

    // ...
}

在上边代码中,MovieRecommender将会装配firstMovieCatalog方法返回的MovieCatalog实例

Fine-tuning Annotation-based Autowiring with Qualifiers

Qualifiers在需要更多的选择条件进行筛选装配Bean时适用

举一个例子:

UserService需要一个UserDao,用@Qualifier指定具有value=main的bean导入

package com.yoke.lab.springbootlab.service;

import com.yoke.lab.springbootlab.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

/**
 * @Author Yoke
 * @Date 2019/01/14 上午8:08
 */
@Service
public class UserService {

    private final UserDao userDao;

    @Autowired
    public UserService(@Qualifier("main") UserDao userDao) {
        this.userDao = userDao;
    }

    public void test() {
        userDao.user();
    }

}
package com.yoke.lab.springbootlab.dao;

/**
 * @Author Yoke
 * @Date 2019/01/23 下午2:15
 */
public interface UserDao {
    void user();
}
package com.yoke.lab.springbootlab.dao;

/**
 * @Author Yoke
 * @Date 2019/01/23 下午2:42
 */
public class UserDaoImpl1 implements UserDao {

    @Override
    public void user() {
        System.out.println("userImpl 1 被注入了");
    }
}
package com.yoke.lab.springbootlab.dao;

/**
 * @Author Yoke
 * @Date 2019/01/23 下午2:43
 */
public class UserDaoImpl2 implements UserDao {
    @Override
    public void user() {
        System.out.println("user dao 2被注入了");
    }
}
package com.yoke.lab.springbootlab.config;

import com.yoke.lab.springbootlab.dao.UserDao;
import com.yoke.lab.springbootlab.dao.UserDaoImpl1;
import com.yoke.lab.springbootlab.dao.UserDaoImpl2;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @Author Yoke
 * @Date 2019/01/23 下午2:41
 */
@Configuration
public class UserConfig {

    @Bean
    @Qualifier("main")
    public UserDao userDao1() {
        return new UserDaoImpl1();
    }

    @Bean
    @Qualifier("action")
    public UserDao userDao2() {
        return new UserDaoImpl2();
    }
}

最终UserService引入会是UserDaoImpl1

我们可以自定义字节的选择注解,只需在自己的注解头上添加上@Qualifier

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface Genre {

    String value();
}

如果想有更加严格的限制,不止有一个value来限定可以这样子

@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public @interface MovieQualifier {

    String genre();

    Format format();
}
public enum Format {
    VHS, DVD, BLURAY
}

在使用该注解时,添加genre,format两个属性

使用@Resource注入

Spring支持使用JSR250@Resource注解

@Resource有一个name的参数,用来指定注入bean的名称

public class SimpleMovieLister {

    private MovieFinder movieFinder;

    @Resource(name="myMovieFinder") 
    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }
}

如果@Resource没有指定name字段,它默认会使用属性的名称/set方法中的属性的名称作为bean的名称

public class SimpleMovieLister {

    private MovieFinder movieFinder;

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

上边这个例子中,将会注入一个名字为moviewFinder的bean

没有明确的名字指定的情况下,它会和@AUtowired类似,通过类型进行注入

使用PostConstruct@PreDestroy

@PostConstruct: 对应Bean的初始化

@PreDestroy: 对应Bean销毁之前的工作

public class CachingMovieLister {

    @PostConstruct
    public void populateMovieCache() {
        // populates the movie cache upon initialization...
    }

    @PreDestroy
    public void clearMovieCache() {
        // clears the movie cache upon destruction...
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值