初始化上下文
使用注解时初始化要用:
ApplicationContext context = new AnnotationConfigApplicationContext();
也需要创建一个配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
至于 Bean 的内容,就可以在配置类中编写:
@Configuration
public class MainConfiguration {
}
@Bean
@Configuration
public class MainConfiguration {
@Bean("student")
public Student student(){
return new Student();
}
}
相当于:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean name = "student" class="com.test.bean.Student"/>
</beans>
使用时还是一样的:
ApplicationContext context = new AnnotationConfigApplicationContext(MainConfiguration.class);
Student student = context.getBean(Student.class);
System.out.println(student);
如果为空则名字默认为小驼峰命名法,即首字母小写,以后的首字母大写。
生命周期和自动装配
可以直接在@Bean中配置:
@Bean(name = "", initMethod = "", destroyMethod = "", autowireCandidate = false)
public Student student(){
return new Student();
}
@Lazy
@Bean
@Lazy(true) //对应lazy-init属性
public Student student(){
return new Student();
}
@Scope
@Bean
@Scope("prototype") //对应scope属性
public Student student(){
return new Student();
}
@DependsOn
@Bean
@DependsOn("teacher") //对应depends-on属性
public Student student(){
return new Student();
}
property 依赖注入
原:
<bean name="teacher" class="com.test.bean.ProgramTeacher"/>
<bean name="student" class="com.test.bean.Student">
<property name="teacher" ref="teacher"/>
</bean>
可以直接放置在方法的参数中表示:
@Configuration
public class MainConfiguration {
@Bean(name = "teacher")
Teacher Teacher() {
return new Teacher();
}
@Bean(name = "student")
Student Student(Teacher teacher){
Student student = new Student();
student.setTeacher(teacher);
return student;
}
}
@Autowired
上面的 property 还得自己在bean中写把参数添加到类中的代码,更方便的是使用 @Autowired
注解直接添加在对应类的字段中:
public class Student {
@Autowired
private Teacher teacher;
}
这样连 set 方法和之前的添加参数代码都省了。
冲突问题 @Qualifier
如果出现像之前那种冲突问题自动装配的歧义问题,可以使用 @Qualifier
指明要匹配的Bean名称:
public class Student {
@Autowired
@Qualifier("a") //匹配名称为a的Teacher类型的Bean
private Teacher teacher;
}
@Component
相比于一个一个给字段/构造方法添加 @Autowire
,我们也可以直接在类前添加 @Component
注解来注册。
@Component("lbwnb") //同样可以自己起名字
public class Student {
}
同时还要在配置类中添加扫描路径:
@Configuration
@ComponentScan("com.test.bean") //包扫描,这样Spring就会去扫描对应包下所有的类
public class MainConfiguration {
}
这样就可以直接对每个构造方法中的参数进行注入:
@Component
public class Student {
Teacher teacher;
public Student(Teacher teacher){ //如果有Teacher类型的Bean,那么这里的参数会被自动注入
this.teacher = teacher;
}
}
@Resource 旧版本
在JDK11版本以后,javax.annotation这个包被移除并且更名为jakarta.annotation,随之而移出的是 @Resource
注解。
@Resource
注解和 @Autowire
作用类似,也可以实现自动装配。
若想新版本使用需要导入包:
<dependency>
<groupId>jakarta.annotation</groupId>
<artifactId>jakarta.annotation-api</artifactId>
<version>2.1.1</version>
</dependency>
使用方法一样,直接替换掉就可以了。
与 Autowire 的区别
- @Resource默认ByName如果找不到则ByType,可以添加到set方法、字段上。
- @Autowired默认是byType,只会根据类型寻找,可以添加在构造方法、set方法、字段、方法参数上。
因为@Resource的匹配机制更加合理高效,因此官方并不推荐使用@Autowired字段注入。
当然,实际上Spring官方更推荐我们使用基于构造方法或是Setter的@Autowired注入,比如Setter 注入的一个好处是,Setter 方法使该类的对象能够在以后重新配置或重新注入。其实,最后使用哪个注解,还是看你自己,要是有强迫症不能忍受黄标但是又实在想用字段注入,那就用@Resource注解。