五、Spring之自动装配
2019-10-28 16:02:12来源:博客园 阅读 ()
五、Spring之自动装配
Spring之自动装配
? Spring利用依赖注入(DI),完成对IOC容器中各个组件依赖关系的赋值。
【1】@Autowired
@Autowired 注解,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。
通过 @Autowired的使用来消除 set ,get方法。在使用@Autowired之前,我们对一个bean配置其属性时,是这样做的:
<property name="属性名" value="属性值"/>
通过这种方式来,配置比较繁琐,而且代码比较多。在Spring 2.5 引入了 @Autowired 注解。
由于该注解比较简单,这里就不再用代码举例说明了,主要来说一下@Autowired的原理和使用它的注意事项。
那么使用@Autowired的原理是什么?
? 其实在启动Spring容器时,容器自动装载了一个AutowiredAnnotationBeanPostProcessor后置处理器,当容器扫描到@Autowied、@Resource或@Inject时,就会在IOC容器自动查找需要的bean,并装配给该对象的属性。
这里说明一下@Resource和@Inject这两个注解:
@Resource是通过JSR250规范实现的,通过CommonAnnotationBeanPostProcessor类实现依赖注入
@Inject是通过JSR330规范实现的,通过AutowiredAnnotationBeanPostProcessor类实现的依赖注入
三个注解的相异之处:
@Autowired和@Inject基本是一样的,因为两者都是使用AutowiredAnnotationBeanPostProcessor来处理依赖注入。但是@Resource是个例外,它使用的是CommonAnnotationBeanPostProcessor来处理依赖注入。当然,两者都是BeanPostProcessor。
? @Resource默认是按照组件名称进行装配的,不能支持@Primary(标注在配置类的Bean上,在自动注入时优先注入该Bean)和@Autowired(required=false)功能
? @Inject需要导入javax.inject包,和@Autowired功能一样,不支持@Autowired(required=false)功能
@Autowired可以标注的位置:
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
? 标注到构造器、参数、方法、属性都是从容器中获取参数组件的值
- 构造器:如果当前类只有一个有参构造器,这个有参构造器上的@Autowired可以省略。
- 方法:在标注@Bean注解的方法上,参数可以不用标注@Autowired注解,也会自动从容器中获取。
【2】Aware
? Spring的依赖注入的最大亮点就是你所有的Bean对Spring容器的存在是没有意识的。即你可以将你的容器替换成别的容器,例如Goggle Guice,这时Bean之间的耦合度很低。
? 但是在实际的项目中,我们不可避免的要用到Spring容器本身的功能资源,这时候Bean必须要意识到Spring容器的存在,才能调用Spring所提供的资源,这就是所谓的Spring Aware。其实Spring Aware本来就是Spring设计用来框架内部使用的,若使用了Spring Aware,你的Bean将会和Spring框架耦合。
? 比如BeanNameAware、BeanFactoryAware、ApplicationContextAware接口。假设我们的类继承了BeanNameAware这个接口,对应这个接口有一个方法setBeanName的方法,spring在依赖注入的初始化阶段会调用生成对象的这个方法,把beanName传为入参传进来。一般我们在会自己写的类里面定义一个属性来接收这个beanName,然后这个beanName我们就可以在开发中使用了。
? 常用的Aware接口:
Aware子接口 | 描述 |
---|---|
BeanNameAware | 获取容器中 Bean 的名称 |
BeanFactoryAware | 获取当前 BeanFactory |
ApplicationContextAware | 获取当前容器 |
MessageSourceAware | 与国际化相关 |
ApplicationEventPublisherAware | 主要用于发布事件 |
ResourceLoaderAware | 获取资源加载器,这样获取外部资源文件 |
? 下面以实现BeanNameAware为例:
public class Person implements BeanNameAware {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person() {
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
'}';
}
@Override
public void setBeanName(String s) {
this.name = s;
}
}
? 在配置类中注入Person
@Configuration
public class MyConfig {
@Bean("Jack")
public Person person(){
return new Person();
}
}
/**在测试类中获取该Bean并打印
Person{name='Jack'}
*/
【3】@Profile
1.Spring中的@Profile 是什么?
? Spring中的Profile功能其实早在Spring 3.1的版本就已经出来,它可以理解为我们在Spring容器中所定义的Bean的逻辑组名称,只有当这些Profile被激活的时候,才会将Profile中所对应的Bean注册到Spring容器中。举个更具体的例子,我们以前所定义的Bean,当Spring容器一启动的时候,就会一股脑的全部加载这些信息完成对Bean的创建;而使用了Profile之后,它会将Bean的定义进行更细粒度的划分,将这些定义的Bean划分为几个不同的组,当Spring容器加载配置信息的时候,首先查找激活的Profile,然后只会去加载被激活的组中所定义的Bean信息,而不被激活的Profile中所定义的Bean定义信息是不会加载用于创建Bean的。
2.@Profile如何使用
? 下面我们定义两个数据源,分别使用@Profile注解指定在测试和开发阶段使用
@Configuration
public class MyConfig {
@Bean
@Profile("test")
public DataSource dataSourceTest() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("root");
return dataSource;
}
@Bean
@Profile("dev")
public DataSource dataSourceDev() throws PropertyVetoException {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.driver");
dataSource.setJdbcUrl("jdbc:mysql:///test");
dataSource.setUser("root");
dataSource.setPassword("root");
return dataSource;
}
}
? 在测试类中我们设置当前激活环境为test:
public class ProfileTest {
@Test
public void test(){
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.setActiveProfiles("test");
applicationContext.register(MyConfig.class);
applicationContext.refresh();
String[] names = applicationContext.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
/**测试结果
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
dataSourceTest
*/
? 在当前环境为test环境时,只有dataSourceTest被注入到容器当中。
? @Profile不仅可以标注到方法上面,还可以标注到类上,即整个类根据环境进行加载。
原文链接:https://www.cnblogs.com/lee0527/p/11755361.html
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:分布式的理论
- Spring系列.ApplicationContext接口 2020-06-11
- springboot2配置JavaMelody与springMVC配置JavaMelody 2020-06-11
- 给你一份超详细 Spring Boot 知识清单 2020-06-11
- SpringBoot 2.3 整合最新版 ShardingJdbc + Druid + MyBatis 2020-06-11
- 掌握SpringBoot-2.3的容器探针:实战篇 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash