【问题标题】:Magic behind @ComponentScan and @Component@ComponentScan 和 @Component 背后的魔法
【发布时间】:2019-11-14 11:05:50
【问题描述】:

我还在深入学习spring依赖注入。

我的第一个类是配置类,我在其中向容器声明以加载和管理在注释方法中声明的 bean。

package ioc.question_004;

import ioc.commun.Person;
import ioc.commun.Profession;
import org.springframework.context.annotation.*;

@Configuration
public class MyConfiguration {

    @Bean
    public Profession profession(){
        return Profession.builder()
                     .name("professor")
                     .description("professor in the university")
                     .build();
    }

    @Bean
    public Person person(){
        return Person.builder()
                     .name("Bagna")
                     .age(52)
                     .profession(profession())
                     .build();
    }

}

我的第二个类是一个 daoRepository,它看起来像:

package ioc.question_008.dao;

import ioc.commun.Person;
import lombok.*;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

@Repository
@Builder
@Setter
@Getter
@EqualsAndHashCode
@ToString
public class MyDaoRepository implements dao {

    List<Person> personList = new ArrayList<>();

    @Override
    public boolean save( Person person ){
        return this.personList.add(person);
    }

    @Override
    public boolean delete( Person person ){
        return  this.personList.remove(person);
    }

}

我的运行代码如下:

@Configuration
@Import(MyConfiguration.class)
@ComponentScan(basePackageClasses = {MyDaoRepository.class} )
public class DependencyInjection {
    public static void main( String[] args ) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DependencyInjection.class);
        dao myDaoRepository = (MyDaoRepository) context.getBean("myDaoRepository");
        System.out.println(myDaoRepository);
    }

}

MyDaoRepository 神奇地包含在配置类 MyConfiguration 中声明的@Bean 人:

MyDaoRepository(personList=[Person(name=Bagna, age=52,professional=Profession(name=professor, 描述=大学教授))])

我认为容器会自动注入这个对象,即使我没有要求。可能是编译器添加了一些 @Autowired 注释。我不确定。

您能否向我解释一下我如何要求 spring 容器不注入 bean,即使它们存在于容器中(例如 bean 人),除非我要求使用 @Autowired 自己进行注入注解。

【问题讨论】:

  • “包含”它是什么意思?存储库中的列表?
  • 是的,列表自动包含在配置类中声明的这个人对象..
  • 如果你告诉Spring(通过组件扫描)自动创建bean本身,你就不能要求Spring不注入bean依赖。如果你想手动控制,不要组件扫描,自己写一个@Bean方法。
  • 可能我的问题并不清楚。 1-我愿意的解决方案是要求依赖注入,但不使用配置类中定义的 person 类型的 bean。(知道包含此配置类对于其他 bean 实例是强制性的,并且删除 @Import 的解决方案将不起作用.) 2-返回我的代码,person对象是如何注入到我的列表中的(构造函数注入、setter方法注入还是字段注入)?

标签: java spring autowired spring-ioc


【解决方案1】:

原因是spring的集合自动装配和lombok的Builder的结合

首先,@Builder 添加了一个全参数构造函数MyDaoRepository(List&lt;Person&gt; list)

其次,spring会自动检测你的工厂方法@Bean public Person person()

现在,由于构造函数需要一个集合,所以 spring 将它可以找到的所有 Person-bean 累积到 List 中,并将其注入构造函数,相应地设置列表。

我认为(但它目前未经测试但已记录 here),在这种情况下,将 @Autowired(required = false) 添加到您的 List&lt;Person&gt; persons 属性是您想要的,因为这将其标记为可选并且 spring 不会注入它。 (编辑:我弄错了,你仍然需要 no-args-constructor 才能工作,但是如果没有任何 @Autowired 注释,列表无论如何都不会以这种方式注入。required=false 只是在没有适当的 @ 时防止异常987654333@ bean 已找到。)

编辑:正如冷冻豌豆的 Roddy 先生所指出的,也可以为 spring 添加一个不同的构造函数来创建你的 bean,例如通过使用 @NoArgsConstructor 注释您的存储库

【讨论】:

  • 理论上也可以为 Spring 添加一个无参数的构造函数来更喜欢:@NoArgsConstructor
  • 是的,我认为他需要像他在存储库中一样的千万亿注释:P 但我想我会提到它,好点,谢谢
  • @Autowired(required = false) 不起作用,因为它意味着注入对象,但如果你没有找到这个对象,请不要抛出异常。
  • NoArgsConstructor 工作完美,在我看来,因为列表上没有 Autowired 注释,但在 no arg 构造函数上。有人可以证实这一点。
  • @stepio,我同意人们应该了解所使用的技术并适当地使用它们。然而,Lombok 也是关于 阅读 更少样板文件(没有来源,但有人说你阅读代码的频率是你编写代码的 10 倍)。 OP 应该考虑是否所有这些 lombok 注释都是必要的(我的观点:它们在那个地方真的很糟糕)。
猜你喜欢
  • 2013-09-30
  • 1970-01-01
  • 2011-01-04
  • 1970-01-01
  • 1970-01-01
  • 2012-05-15
  • 2012-11-30
  • 2011-04-02
  • 2010-09-24
相关资源
最近更新 更多