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-330
中javax.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...
}
}