【Spring】四种依赖注入方式(xml、注解)

心已赠人 2022-10-31 01:47 309阅读 0赞

DI(DependencyInjection)依赖注入:就是指对象是被动接受依赖类而不是自己主动去找,换句话说就。是指对象不是从容器中查找它依赖的类,而是在容器实例化对象的时候主动将它依赖的类注入给它。

1.set方法注入

  1. public class Student {
  2. private String name;
  3. private Teacher teacher;
  4. public String getName() { return name;}
  5. public void setName(String name) { this.name = name;}
  6. public Teacher getTeacher() { return teacher; }
  7. public void setTeacher(Teacher teacher) { this.teacher = teacher; }
  8. }
  9. public class Teacher {
  10. private String name;
  11. public String getName() { return name; }
  12. public void setName(String name) { this.name = name; }
  13. }

1.xml形式

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  3. <!-- 创建一个id=teacher的Teacher -->
  4. <bean id="teacher" class="test.Teacher">
  5. <property name="name" value="李四"/>
  6. </bean>
  7. <!-- 创建一个id=student的Student -->
  8. <bean id="student" class="test.Student">
  9. <property name="name" value="张三"/>
  10. <!-- 将teacher注给student -->
  11. <property name="teacher" ref="teacher"/>
  12. </bean>
  13. </beans>

2.注解

  1. @Configuration
  2. public class BeansConfiguration {
  3. @Bean
  4. // 这个bean的name=student
  5. public Student student(){
  6. Student student=new Student();
  7. student.setName("张三");
  8. student.setTeacher(teacher());
  9. return student;
  10. }
  11. @Bean
  12. // name=student
  13. public Teacher teacher(){
  14. Teacher teacher=new Teacher();
  15. teacher.setName("李四");
  16. return teacher;
  17. }
  18. }
  19. public class Main {
  20. public static void main(String args[]){
  21. FileSystemXmlApplicationContext context=new
  22. FileSystemXmlApplicationContext("applicationContext.xml的绝对路径");
  23. // 容器中拿出来的student张三就是被注入过student的
  24. Student student= (Student) context.getBean("student");
  25. Teacher teacher= (Teacher) context.getBean("teacher");
  26. System.out.println("学生的姓名:"+student.getName()+"。老师
  27. 是"+student.getTeacher().getName());
  28. System.out.println("老师的姓名:"+teacher.getName());
  29. }
  30. }

2.构造方法注入

  1. public class Student {
  2. private String name;
  3. private Teacher teacher;
  4. public Student(String name,Teacher teacher) {
  5. this.name = name;
  6. this.teacher = teacher;
  7. }
  8. }
  9. public class Teacher {
  10. private String name;
  11. public String getName() { return name; }
  12. public void setName(String name) { this.name = name; }
  13. }

1.xml形式

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  3. <!-- 创建Teacher实例teacher -->
  4. <bean name="teacher" class="test.Teacher">
  5. <property name="name" value="李四"></property>
  6. </bean>
  7. <bean name="student" class="test.Student">
  8. <!-- 注入 teacher 这个 bean -->
  9. <constructor-arg ref="teacher" />
  10. </bean>
  11. </beans>

2.注解

  1. @Configuration
  2. public class MainConfig {
  3. // 这个bean没必要注入IOC容器
  4. public Teacher teacher() {
  5. return new Teacher();
  6. teacher.setName = "李四";
  7. }
  8. // 创建一个bean student
  9. @Bean
  10. public Student student() {
  11. return new Student(teacher());
  12. }
  13. }

3.自动注入

自动注入就是根据当前对象中定义的实例变量名进行注入

1.xml形式:byName + byType

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <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 http://www.springframework.org/schema/beans/spring-beans.xsd">
  3. <!-- 创建Teacher实例teacher -->
  4. <bean id="teacher" class="test.Teacher">
  5. <property name="name" value="李四"/>
  6. </bean>
  7. <!-- 创建Student实例student -->
  8. <!-- byName 会自动给未初始化实例变量找能匹配的bean注入进来 -->
  9. <bean id="student" class="test.Student" autowire="byName">
  10. <property name="name" value="张三"/>
  11. </bean>
  12. </beans>

2.注解形式:@Autowired + @Value

@Autowired

  • 自动装配首先时按照类型进行装配,若在IOC容器中发现多个相同类型的组件,那么就按照属性名称来进行装配
  • @Qualifier(“name”):可以在容器中有多个同一类的bean时指定name。比如 Teacher有teacher1,teacher2,那么我们就可以 @Autowired @Qualifier(“teacher1”) 指定teacher1注入。

@Autowired 和 @Resource:

  • 共同点:@Resource和@Autowired都可以作为注入属性的修饰,在接口仅有单一实现类时,两个注解的修饰效果相同,可以互相替换,不影响使用。
  • 不同点:

    • @Autowired是spring的注解,是spring2.5版本引入的,Autowired只根据type进行注入,不会去匹配name。如果涉及到type无法辨别注入对象时,那需要依赖@Qualifier或@Primary注解一起来修饰。
    • @Resource 是JDK1.6支持的注解, 默认按照名称进行装配,名称可以通过name属性进行指定,如果没有指定name属性,当注解写在字段上时,默认取字段名,按照名称查找。如果注解写在setter方法上默认取属性名进行装配。
      当找不到与名称匹配的bean时才按照类型进行装配。但是需要注意的是,如果name属性一旦指定,就只会按照名称进行装配。

一般推荐使用 @Autowired,当需要指定 beanName 时再用 @Resource。

@Value

  • @Value(value):给当前变量直接注入指定值value,类型要对应
  • @Value(“#{configProperties[‘key’]}“):表示SpEl表达式通常用来获取bean的属性,或者调用bean的某个方法。当然还有可以表示常量
  • @Value(“${key}“):可以获取对应属性文件中定义的属性值。

    // 将Teacher的实例teacher注入IOC容器
    @Component(“teacher”)
    public class Teacher {

    1. @Value("李四") // 为name注入String值,李四
    2. private String name;
    3. public String getName() {
    4. return name;
    5. }
    6. public void setName(String name) {
    7. this.name = name;
    8. }

    }

    // 将Student实例student注入IOC容器
    @Component(“student”)
    public class Student {

    1. @Value("张三")
    2. private String name; // name = 张三
    3. @Resource
    4. private Teacher teacher; // 通过名字 teacher 去寻找bean,找到了注入进去
    5. public String getName() {
    6. return name;
    7. }
    8. public void setName(String name) {
    9. this.name = name;
    10. }
    11. public Teacher getTeacher() {
    12. return teacher;
    13. }
    14. public void setTeacher(Teacher teacher) {
    15. this.teacher = teacher;
    16. }

    }

4.依赖方法注入(lookup-method)

当一个单例的Bean,依赖于一个多例的Bean,用常规方法只会被注入一次,如果每次都想要获取一个全新实例就可以采用lookup-method 方法来实现。该操作的原理是基于动态代理技术,重新生成一个继承至目标类,然后重写抽像方法到达注入目的。

前面说所单例Bean依赖多例Bean这种情况也可以通过实现 ApplicationContextAware 、BeanFactoryAware 接口来获取BeanFactory 实例,从而可以直接调用getBean方法获取新实例,推荐使用该方法,相比lookup-method语义逻辑更清楚一些。

  1. <bean id="MethodInject" class="com.my.spring.MethodInject">
  2. <lookup-method name="getFine" bean="fine"></lookup-method>
  3. </bean>
  4. // 编写一个抽像类
  5. public abstract class MethodInject {
  6. public void handlerRequest() {
  7. // 通过对该抽像方法的调用获取最新实例
  8. getFine();
  9. }
  10. // 编写一个抽像方法
  11. public abstract FineSpring getFine();
  12. }
  13. // 设定抽像方法实现

发表评论

表情:
评论列表 (有 0 条评论,309人围观)

还没有评论,来说两句吧...

相关阅读

    相关 spring依赖注入方式

    平常的java开发中,程序员在某个类中需要依赖其它类的方法,则通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理,spring提出了依赖注

    相关 spring依赖注入方式

    平常的java开发中,程序员在某个类中需要依赖其它类的方法,通常是new一个依赖类再调用类实例的方法,这种开发存在的问题是new的类实例不好统一管理。 spring提出了依赖