Spring注解版-自动装配

@Autowired&@Qualifier@Primary

@Autowired
自动装配也就是依赖注入(DI): 为容器中的组件自动装配其依赖其他组件;

  1. 先通过属性的类型匹配容器中的组件, 匹配到有且只有一个就自动注入属性
	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有且只有一个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 自动注入时通过组件类型匹配 自动装配
		@Autowired
		private BookServiceImpl bookService;
	}
  1. 如果在容器中匹配到多个同样类型的组件, 则再通过属性的名称匹配组件;
	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}

		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookServiceImpl(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 自动注入时通过组件类型匹配 自动装配 如果找到多个, 则再通过属性名称查找 这里注入的一定是 id为 bookService的组件
		@Autowired
		private BookServiceImpl bookService;
	}
  1. 其属性 required = true 表示 必须自动注入成功,Spring才会进行下一步操作,例如初始化组件, 否则会报org.springframework.beans.factory.NoSuchBeanDefinitionException异常, 表示没有找到对应属性的组件信息BeanDefinition; 如果设置为false, Spring不会检测属性是否存在于容器中, 不管有没有注入成功, 都会进行下一步;
	@Configuration
	public class SpringConfig {
		// Spring容器并没有注册BookServiceImpl 类相关的组件
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 容器中不存在任何BookServiceImpl 类型的组件, 此时bookService属性会为Null
		@Autowired(required=false)
		private BookServiceImpl bookService;
	}
  1. @Autowired可以标注在构造器上, setter方法上, 方法的参数上, 属性上;
	/**1*/
	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 标注在属性上
		@Autowired
		private BookServiceImpl bookService;
	}
	/**2*/
	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		private BookServiceImpl bookService;
		// 标注在setter方法上
		@Autowired
		public void setBookService(BookServiceImpl bookService) {
			this.bookService = bookService;
		}
	}
	/**3*/
	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		private BookServiceImpl bookService;
		// 标注在构造器上, 如果当前组件只有一个有参构造器时, @Autowired可以省略
		@Autowired
		public void BookAuthorServiceImpl (BookServiceImpl bookService) {
			this.bookService = bookService;
		}
	}
	/**4*/
	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {	
		private BookServiceImpl bookService;
		// 标注在参数上, 如果当前组件只有一个有参构造器时, @Autowired可以省略
		public void BookAuthorServiceImpl (@Autowired BookServiceImpl bookService) {
			this.bookService = bookService;
		}
	}

	/**5*/
	// 在@Bean标注的方法上自动注入
	@Configuration
	public class SpringConfig {	
		// 这里的@Autowired可以省略,Spring会自动注入bookService
		@Bean
		public BookAuthorServiceImpl bookAuthorServiceImpl (@Autowired BookServiceImpl bookService){
			BookAuthorServiceImpl bookAuthorServiceImpl = new BookAuthorServiceImpl();
			bookAuthorServiceImpl.setBookService(bookService);
			return bookAuthorServiceImpl;
		}
	}
	public class BookAuthorServiceImpl {
		private BookServiceImpl bookService;
		public void BookAuthorServiceImpl (BookServiceImpl bookService) {
			this.bookService = bookService;
		}
	}

@Qualifier
当自动装配时同样类型的匹配到多个组件, @Autowired可以搭配@Qualifier注解指定名称来匹配组件;

	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}

		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookServiceImpl(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 自动注入时通过组件类型匹配 自动装配 如果找到多个, 由于@Qualifier注解指定了名称 这里注入的一定是 id为 bookServiceImpl的组件
		@Qualifier("bookServiceImpl")
		@Autowired
		private BookServiceImpl bookService;
	}

@Primary
Spring进行自动装配的时候, 默认使用被@Primary注解标注的bean; 不能与@Qualifier 一起使用; 如果使用了@Qualifier, 那么@Qualifier优先级大于@Primary;

	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}

		@Primary
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookServiceImpl(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		// 自动注入时通过组件类型匹配 自动装配 如果找到多个, 由于@Primary注解指定首选bean 这里注入的一定是 id为 bookServiceImpl的组件
		@Autowired
		private BookServiceImpl bookService;
	}
@Resource&@Inject

@Resource
Spring支持java规范中的@Resource注解, 可以和@Autowired一样可以自动装配, 但只会根据名称匹配组件;且不能搭配@Primary使用, 也不能指定required=false;

	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}

		@Primary
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookServiceImpl(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		//根据名称匹配 这里注入的是id为 bookService的组件
		@Resource
		private BookServiceImpl bookService;
	}

@Inject
Spring支持java规范中的@Inject注解, 想要使用这个注解, 需要导入jar包依赖; 支持@Primary注解搭配使用, 但不支持指定required=false;

<dependency>
	<groupId>javax.inject</groupId>
	<artifactId>javax.inject</artifactId>
	<version>1</version>
</dependency>
	@Configuration
	public class SpringConfig {
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookService(){
			return new BookServiceImpl();
		}

		@Primary
		@Bean // 容器中关于BookServiceImpl类型的组件有多个
		public BookServiceImpl bookServiceImpl(){
			return new BookServiceImpl();
		}
	}

	@Service("bookAuthorService")
	public class BookAuthorServiceImpl {
		//根据名称匹配 这里注入的是id为 bookService的组件
		@Resource
		private BookServiceImpl bookService;
	}

Aware
如果组件中需要注入Spring底层的组件, 则可以将组件实现Aware接口的子接口, 重写这些子接口的方法, 来自动注入Spring底层的组件;
在组件实现这些Aware接口后, Spring会通过对应xxxAwareProcessor后置处理器回调组件重写的方法, 将Spring的底层组件注入 ;
在这里插入图片描述

@Service("bookService")
public class BookServiceImpl implements ApplicationContextAware{
	
	// 重写ApplicationContextAware接口的setApplicationContext方法, 自动注入ApplicationContext 
	private ApplicationContext applicationContext;
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		this.applicationContext = applicationContext;
	};
	
}

// xxxAwareProcessor后置处理器源码
class ApplicationContextAwareProcessor implements BeanPostProcessor {

	private final ConfigurableApplicationContext applicationContext;

	private final StringValueResolver embeddedValueResolver;


	/**
	 * Create a new ApplicationContextAwareProcessor for the given context.
	 */
	public ApplicationContextAwareProcessor(ConfigurableApplicationContext applicationContext) {
		this.applicationContext = applicationContext;
		this.embeddedValueResolver = new EmbeddedValueResolver(applicationContext.getBeanFactory());
	}

	// Spring在组件初始化之前调用的方法, 在bean的生命周期中学习过
	@Override
	public Object postProcessBeforeInitialization(final Object bean, String beanName) throws BeansException {
		AccessControlContext acc = null;

		if (System.getSecurityManager() != null &&
				(bean instanceof EnvironmentAware || bean instanceof EmbeddedValueResolverAware ||
						bean instanceof ResourceLoaderAware || bean instanceof ApplicationEventPublisherAware ||
						bean instanceof MessageSourceAware || bean instanceof ApplicationContextAware)) {
			acc = this.applicationContext.getBeanFactory().getAccessControlContext();
		}

		if (acc != null) {
			AccessController.doPrivileged(new PrivilegedAction<Object>() {
				@Override
				public Object run() {
					invokeAwareInterfaces(bean);
					return null;
				}
			}, acc);
		}
		else {
			// 这里就是回调组件方法的地方
			invokeAwareInterfaces(bean);
		}

		return bean;
	}

	private void invokeAwareInterfaces(Object bean) {
		if (bean instanceof Aware) {
			if (bean instanceof EnvironmentAware) {
				((EnvironmentAware) bean).setEnvironment(this.applicationContext.getEnvironment());
			}
			if (bean instanceof EmbeddedValueResolverAware) {
				((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
			}
			if (bean instanceof ResourceLoaderAware) {
				((ResourceLoaderAware) bean).setResourceLoader(this.applicationContext);
			}
			if (bean instanceof ApplicationEventPublisherAware) {
				((ApplicationEventPublisherAware) bean).setApplicationEventPublisher(this.applicationContext);
			}
			if (bean instanceof MessageSourceAware) {
				((MessageSourceAware) bean).setMessageSource(this.applicationContext);
			}
			if (bean instanceof ApplicationContextAware) {
				((ApplicationContextAware) bean).setApplicationContext(this.applicationContext);
			}
		}
	}

	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) {
		return bean;
	}

}

@Profile
使用此注解可以指定特定环境下才注入组件; @Profile("default")表示默认使用此bean

@Configuration(value="config")
@PropertySource({"classpath:application.properties"})
public class SpringConfig {
	
	@Value("${db.url}")
	private String url;
	@Value("${db.user}")
	private String username;
	@Value("${db.password}")
	private String password;
	@Value("${db.driverClass}")
	private String driverClass;
	
	// 在开发环境下注册
	@Profile("dev")
	@Bean
	public DataSource dataSourceDev() throws Exception {
		Properties properties = new Properties();
		properties.put("url", url);
		properties.put("username", username);
		properties.put("password", password);
		properties.put("driverClassName", driverClass);
		DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
		return dataSource;
	}
	
	// 在测试环境下注注册
	@Profile("test")
	@Bean
	public DataSource dataSourceTest() throws Exception {
		Properties properties = new Properties();
		properties.put("url", url);
		properties.put("username", username);
		properties.put("password", password);
		properties.put("driverClassName", driverClass);
		DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
		return dataSource;
	}
	
	// 在生产环境下注册
	@Profile("pro")
	@Bean
	public DataSource dataSourcePro() throws Exception {
		Properties properties = new Properties();
		properties.put("url", url);
		properties.put("username", username);
		properties.put("password", password);
		properties.put("driverClassName", driverClass);
		DataSource dataSource = DruidDataSourceFactory.createDataSource(properties);
		return dataSource;
	}
}


public class Test {
	@org.junit.Test
	public void test() {
		AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
		// 设置容器的环境为开发环境
		context.getEnvironment().setActiveProfiles("dev");
		// 注册配置类
		context.register(SpringConfig.class);
		// 刷新容器
		context.refresh();
		// 这里被注册的DataSource一定是dataSourceDev
		String[] beanDefinitionNames = context.getBeanDefinitionNames();
		for (String string : beanDefinitionNames) {
			System.err.println(string);
		}
		context.close();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值