文章目录
常用注解
@Value和@PropertySource
介绍
@Value介绍:
– 1)直接写数据
– 2)SpEL #{ }表达式,
– 3)${}形式,用于获取【properties】中的值(可以通过环境变量获取)
@PropertySource:将配置文件中的变量加载到环境变量中
使用案例
配置类:
@PropertySource(value={"classpath:/person.properties"})
@Configuration
public class MainConfigOfPropertyValues {
@Bean
public Person person(){
return new Person();
}
}
实体类
@Data
public class Person {
@Value("张三")
private String name;
@Value("#{20-2}")
private Integer age;
@Value("${person.nickName}")
private String nickName;
}
测试类如下:
public class IOCTest_PropertyValue {
AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfigOfPropertyValues.class);
@Test
public void test01(){
printBeans(applicationContext);
System.out.println("=============");
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
ConfigurableEnvironment environment = applicationContext.getEnvironment();
String property = environment.getProperty("person.nickName");
System.out.println(property);
applicationContext.close();
}
}
@AutoWired、@Qulifer 、@Primary
介绍
1)、@Autowired:自动注入默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值,找不到就按照Id去找,
@Autowired(required=false),该组件不存在也不会报错2)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字3)、@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
使用总结
-1) . 出现类型相同
但id 不同
的组件,调用下面方法会报错(expected single matching bean but found 2: com.atguigu.dao.BookDao,bookDao2)
applicationContext.getBean("bookDao")
-2). 出现类型相同
且id相同
的两个组件,在装配的时候后者会把前者的替换掉
-3)@Autowired(required=true),如果注入的组件找不到,会报以下错误
UnsatisfiedDependencyException: Error creating bean with name 'bookService': Unsatisfied dependency expressed through field 'bookDao';
Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
-4) @Resource、@Inject、@Autowired 使用对比
@Resource(JSR250):
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能
没有支持@Autowired(reqiured=false);
@Inject@Inject(JSR330):
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;
@Autowired:Spring定义的;
@Resource、@Inject都是java规范
方法、构造器位置自动装配
@AutoWired 可以在构造器和set方法上使用,都是依赖容器中的组件进行自动的注入。
案例
构造方法的注入,自动注入,可以不用写@Auowired
@Component
public class Boss {
private Car car;
//构造器要用的组件,都是从容器中获取
public Boss(Car car){
this.car = car;
System.out.println("Boss...有参构造器");
}
}
其他方法的注入,必须加@Autowired
@Component
public class Car {
private Blue blue;
public Car() {
System.out.println("car constructor...");
}
@Autowired
public void setBlue111(Blue blue) {
System.out.println("car -----> setBlue");
this.blue = blue;
}
}
@Bean 形式的注入,可以不用写@Autowired
@Configuration
@ComponentScan({"com.atguigu.service","com.atguigu.dao","com.atguigu.controller"})
@Import(value = {Car.class, Boss.class, Blue.class})
public class MainConifgOfAutowired {
/** * @Bean标注的方法创建对象的时候,方法参数的值从容器中获取 * @param car * @return */
@Bean
public Color color(Car car){
Color color = new Color();
color.setCar(car);
return color;
}
}
xxAware设置属性的加载流程分析
简介:自定义组件想要使用Spring容器底层的一些组件(ApplicationContext,BeanFactory,xxx);
自定义组件实现xxxAware
;在创建对象的时候,会调用接口规定的方法注入相关组件;Aware;
把Spring底层一些组件注入到自定义的Bean中;
xxxAware:功能使用xxxProcessor;
ApplicationContextAware==》ApplicationContextAwareProcessor;
案例
我们以Aware 的注入spring容器底层组件为例,分析XXAware的执行流程。
@Component
public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
private ApplicationContext applicationContext;
private Blue blue;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
==断点== System.out.println("传入的ioc:" + applicationContext);
this.applicationContext = applicationContext;
}
@Override
public void setBeanName(String name) {
System.out.println("当前bean的名字:" + name);
}
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
String resolveStringValue = resolver.resolveStringValue("你好 ${os.name} 我是 #{20*18}");
System.out.println("解析的字符串:" + resolveStringValue);
System.out.println("bule " + blue.toString());
}
//对象创建并赋值之后调用
@PostConstruct
public void init() {
System.out.println("Red....@PostConstruct...");
}
//容器移除对象之前
@PreDestroy
public void detory() {
System.out.println("detory....@PreDestroy...");
}
@Autowired
private void setBlue(Blue blue) {
==断点== this.blue = blue;
}
}
测试方法与上边类似,使用时,只需要把上边这个Red类加入到容器中,在标有断点的地方打上断点。
由以上打断堆栈分析得出下面结论:
AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
register(annotatedClasses);
refresh();
}
⬇️
//实例化剩下的不是懒加载的 单实例Bean
finishBeanFactoryInitialization(beanFactory);
⬇️
beanFactory.preInstantiateSingletons();
⬇️
// ? 构造器执行,创建一个Bean
getBean(beanName);
⬇️
doGetBean
⬇️
getSingleton
⬇️
doCreateBean{
//将需要Autowired 的属性方法执行一遍
populateBean(beanName, mbd, instanceWrapper);
initializeBean(beanName, exposedObject, mbd){
// aware 方法执行,给实现了xxAware的方法设置值
invokeAwareMethods(beanName, bean);
applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName){
beanProcessor.postProcessBeforeInitialization(result, beanName){
invokeAwareInterfaces(bean){
((EmbeddedValueResolverAware) bean).setEmbeddedValueResolver(this.embeddedValueResolver);
}
}
}
// 初始化方法,执行init
invokeInitMethods(beanName, wrappedBean, mbd);
applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
}