Spring 核心(IOC)- 基于注解的容器配置

    技术2022-07-12  82

    目录

    基于注解的容器配置1. 使用@Autowired2.使用@Order3. 使用@Primary4. 使用@Qualifier5. 使用@Resource6. 使用@Value7. 使用@PostConstruct和@PreDestroy

    基于注解的容器配置

    注解配置和XML配置实现的功能是一样的,只是实现方式不同而已。并且,注解配置在XML配置之前执行。

    首先通过在XML中通过配置可以隐式的注册一些组件,当然你也可以显式的定义bean。(注意引入context命名空间)

    <context:annotation-config/>

    隐式注册包含的组件有:AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor和RequiredAnnotationBeanPostProcessor。

    1. 使用@Autowired

    使用@Autowired实现注解式自动装配。

    @Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Autowired { //指定此依赖性是否为非必须,默认true。 boolean required() default true; }

    通常作用在变量上或方法上,首先按照byType注入,只要容器中有唯一的bean对象类型相匹配,则注入成功,若无匹配,则报错,若匹配多个,则在其中再按照byName注入,若无匹配,则报错。此时set方法不是必须的了,见上文可知。

    四种形式案例:

    作用在构造方法上

    public class UserServie { private UserDao userDao; @Autowired public UserServie(UserDao userDao) { this.userDao = userDao; } }

    在单一构造方法场景下,即使不使用@Autowired注解,也会被用来进行自动装配。

    在单一构造方法场景下,使用@Autowired注入存在着特殊规则,如多元素注入(数组、集合、Map等),在没有匹配bean时允许为空解析。

    在多个构造方法场景下,所有构造方法的@Autowired必须设置required为false,以便其都作为自动装配的候选,自动装配会选择Spring容器匹配bean可以满足最大数量依赖项的构造方法,若无匹配,则选择主选项或默认项构造方法。

    作用在set方法上

    public class UserServie { private UserDao userDao; @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } }

    作用在多个参数方法上

    public class UserServie { private UserDao userDao; private ClubDao clubDao; @Autowired public void prepare(UserDao userDao, ClubDao clubDao) { this.userDao = userDao; this.clubDao = clubDao; } }

    作用在字段上

    public class UserServie { @Autowired private UserDao userDao; //@Autowired 也可以和构造方法混用 public UserServie(UserDao userDao) { this.userDao = userDao; } }

    在XML配置的自动装配中,属性是通过set方法进行set注入的,而在注解注入中注解作用在字段上则可以不需要set方法。其原因是:@autowired注解关闭了访问控制权限,不再需要通过set注入了,直接通过已开放的属性通过Java反射机制进行注入(即使它是私有的)。

    你还可以为复杂/集合类型进行注解注入,前提该类型bean以配置在容器中(建议在注入集合类型bean时,使用XML配置方式和注解配置方式混用)

    Spring5版本中,你还可以在方法形参上使用@Nullable注解来使这个参数允许为空。

    你也可以使用@Autowired注入一些可解析的依赖项:BeanFactory, ApplicationContext, Environment, ResourceLoader, ApplicationEventPublisher和MessageSource,或是其扩展接口ConfigurableApplicationContext 、 ResourcePatternResolver。

    2.使用@Order

    通过@Order注解使用在不同地方拥有不同的功能,数字越小优先级越高:

    使用在@Bean方法或组件类上时,可以在注入时调整其优先级顺序。(如对数组/集合类型进行注入时,集合项中的顺序由@Order决定)使用在配置类中,可以调整这些配置类容器的初始化顺序。

    注意:@Order并不会影响Bean的单例启动顺序(加载顺序)。

    3. 使用@Primary

    由于byType方式自动装配可能会匹配多个候选对象,因此我们通常对于选择需要更多的控制,我们可以使用@Primary实现候选优先权,当多个bean成为候选对象时,应优先考虑@Primary标记的bean。

    //这是基于Java的容器配置方式 @Configuration public class MovieConfiguration { @Bean @Primary public MovieCatalog firstMovieCatalog() { ... } @Bean public MovieCatalog secondMovieCatalog() { ... } // ... } //这是基于注解的容器配置方式 @Primary @Component public class FirstMovieCatalog implements MovieCatalog{ // ... }

    当然,你也可以在XML中进行配置,见上文。

    4. 使用@Qualifier

    通过@Qualifier搭配@Autowired组合实现byName方式自动装配。(不能单独使用)

    作用在字段上:

    public class UserServie { @Autowired @Qualifier("userDao") private ParentDao parentDao; }

    作用在方法参数上:

    public class UserServie { private ParentDao parentDao; @Autowired public void setUserDao(@Qualifier("userDao") ParentDao parentDao) { this.parentDao = parentDao; } }

    使用@Qualifier并不意味着与byType无关,自动装配其实还是先通过byType筛选出候选对象,再通过指定的限定符(@Qualifier值)找出指定对象的。如果要避开类型匹配的过程,可以使用@Resource注解,后续会讲解。

    如果你尝试将来自@Bean方法的返回结果注入到同一配置类中,建议将要注入bean的@Bean方法设置为静态方法,将其与配置类实例和生命周期解耦合。原因是自动装配会优先选择其他配置类的候选对象,而本配置类的候选对象会放在最后选择。

    同时,你还可以通过泛型作为隐式的限定符来代替@Qualifier。

    @Autowired private Store<String> s1; @Autowired private Store<Integer> s2;

    此外,你还可以自定义@Qualifier注解,详见官方文档

    5. 使用@Resource

    Spring也支持JSR-250中的@Resource注解进行自动装配。它可以看作是byName形式的自动装配,通过其属性name来指定限定符。与@Autowired相比,它并没有类型匹配的过程,完全通过限定符进行匹配。

    public class UserServie { @Resource(name="userDao") private ParentDao parentDao; public void setUserDao(ParentDao parentDao) { this.parentDao = parentDao; } }

    若你没有写name属性,它默认的会按照字段名或set方法名进行匹配。

    6. 使用@Value

    你可以通过@Value注解进行基本类型、String类型的注入。此外,它还支持${}和SpEL表达式。

    注入字面量:

    public class User{ @Value("张三") private String name; @Value("aa,bb,cc,dd") private String[] alias; //... }

    Spring提供的内置转换器支持简单类型和String类型的类型转换,多个逗号分隔可以自动转换为数组。

    注入属性文件的属性值:

    public class User{ @Value("${userconfig.name}") private String name; //... }

    注入SpEL表达式:

    public class User{ @Value("#{10+2}") private int age; //... }
    7. 使用@PostConstruct和@PreDestroy

    你可以通过JSR-250生命周期的@PostConstruct和@PreDestroy来实现创建和销毁时的回调方法。

    @Resource、@PostConstruct和@PreDestroy注解都是由CommonAnnotationBeanPostProcessorBean识别的,而这个Bean一般通过隐式的注册,也就是<context:annotation-config/>完成的。

    需要注意的是,在JDK9中,整个javax.annotation注解包从Java源码模块分离出来,而在JDK11中完全移除,需要Maven进行依赖加入才能使用(wdnmd),同时JSR-330也是需要依赖加入才能使用的。

    Processed: 0.010, SQL: 9