初始化上下文

使用注解时初始化要用:

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注解。