我使用spring组件扫描来自动检测bean:
@ComponentScan({"com.org.x, com.org.y"})
Run Code Online (Sandbox Code Playgroud)
问题是我想要com.org.x扫描所有类,但我想要一个单独的类com.org.y.SomeService.class,单独扫描com.org.y
我怎样才能做到这一点?
除了使用上下文扫描之外,我如何创建这个bean并注入应用程序上下文?
我有一个抽象的 Spring 配置类,其中包含一个公共 bean:
public abstract class AbstractConfig {
@Bean
public CommonBean commonBean {
CommonBean commonBean = new CommonBean();
commonBean.specifics = getSpecifics();
};
public abstract String getSpecifics();
}
Run Code Online (Sandbox Code Playgroud)
普通 bean 的细节由其子类设置:
package realPackage;
@Configuration
public class RealConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "real";
}
}
Run Code Online (Sandbox Code Playgroud)
...和...
package testPackage;
@Configuration
@ComponentScan(basePackages = {"testPackage", "realPackage" })
public class TestConfig extends AbstractConfig {
@Override
public String getSpecifics() {
return "test";
}
}
Run Code Online (Sandbox Code Playgroud)
我的测试只需要使用TestConfig并且不应该知道RealConfig(但确实需要访问中的其他组件realPackage)。它始于: …
在Spring Boot 的文档中明确指出,自动配置必须通过spring.factories文件指定自动配置:
\n\n自动配置必须仅以这种方式加载。确保它们是在特定的包空间中定义的,并且它们永远不是组件扫描的目标。
\n
我确实尝试@Component在我的自动配置类上添加一个,并确保它会被组件扫描所拾取。似乎有效。
虽然我确实认为这是不好的做法,因为组件扫描不太可能在现实世界中真正拾取它,但我想知道为什么文档对此有如此强烈的感觉。是否还有其他我未能预料到的危险?如果有,是哪些?
\n编辑:\n在https://youtu.be/jDchAEHIht0?t=734 St\xc3\xa9phane 和 Brian 解释说,有两个阶段,一个称为“用户配置阶段”,另一个称为“自动配置阶段”。按照这种想法,建议使用@ComponentScan自动配置类会将其移至“用户配置阶段”,这基本上会破坏自动配置的语义。
然而,我在实验中未能打破它。只要我保留@Conditional注释,它似乎就能按预期工作......
我正在尝试禁用真正的 Mongo 连接并在测试中用 Fongo 模拟替换它。
这是我的测试课:
@SpringBootTest
@RunWith(SpringRunner.class)
public class ControllerTest {
@Autowired
private WebApplicationContext wac;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private MyService service;
private MockMvc mockMvc;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void performTest() throws Exception {
... logic ...
}
}
Run Code Online (Sandbox Code Playgroud)
除非我尝试添加更改此行的配置文件,否则它工作正常:
@SpringBootTest
Run Code Online (Sandbox Code Playgroud)
对此:
@SpringBootTest(classes = TestConfig.class)
Run Code Online (Sandbox Code Playgroud)
配置类本身:
@Configuration
@ComponentScan
@EnableMongoRepositories
public class TestConfig extends AbstractMongoConfiguration {
@Override
protected String getDatabaseName() {
return "FongoDB";
}
@Override
public Mongo mongo() {
return new Fongo(getDatabaseName()).getMongo(); …Run Code Online (Sandbox Code Playgroud) 我正在尝试@Enable为 Spring 框架编写自己的注释,应按如下方式使用:
package com.example.package.app;
@SpringBootApplication
@com.example.annotations.EnableCustom("com.example.package.custom")
public class MyApplication {}
Run Code Online (Sandbox Code Playgroud)
我使用自定义注释遵循Component scan,但这带来了几个限制:
我不能使基本包属性动态化,即我不能传递"com.example.package.base",但需要在配置中预定义包。
我看了看@AliasFor,但无法让它工作。
当我省略基础包时,扫描从注释的定义包开始,而不是从被注释的类的包开始。在上面的例子中,它只会为 中的类扫描和创建 bean com.example.annotations,而不是为com.example.package.*.
我看了一下EntityScanPackages.Registrar.class在@EntityScan注释中导入的是哪个,但它是一个内部类,我的注释无法导入。
一切正常,如果我把@ComponentScan(includeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, value = MyAnnotation.class))在MyApplication类,但停止时这个被移动到的元注释工作@EnableCustom。如何告诉 Spring Framework 将其视为@EnableCustom指定@ComponentScan某些默认值的不同方式。我试着元注解注释我用@Configuration,@Component和其他人,但没有成功:
@Configuration
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@ComponentScan(
includeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
value = ApplicationService.class))
public @interface EnableApplicationServices {
@AliasFor(annotation …Run Code Online (Sandbox Code Playgroud) java spring spring-annotations component-scan spring-autoconfiguration
我有一个集成测试类,注释如下
@WebAppConfiguration
@ContextConfiguration(classes = {AppConfiguration.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class CacheConsumerTest {
}
Run Code Online (Sandbox Code Playgroud)
这是我的AppConfiguration
@Configuration
@ComponentScan(basePackages = {"com.etc.etc.etc."})
@EnableWebMvc
public class AppConfiguration {
}
Run Code Online (Sandbox Code Playgroud)
出于某种原因,我的@Component豆子都没有@PreDestroy在所有测试结束时被调用CacheConsumerTest.@PostConstruct然而,在任何测试运行之前,都会在开始时调用它.
谁知道问题可能是什么?我的@Component一些后台线程我想关闭(通过调用@Predestroy),否则他们在后台执行的工作将导致其他测试类中的后续测试失败.
我试过添加,@DirtiesContext(classMode=ClassMode.AFTER_CLASS) 但没有帮助.
编辑:找出问题,我必须做一个额外的步骤,使DirtiesContext工作: Spring @DirtiesContext重新加载Spring上下文?
我在防止Spring Boot自动配置某些类(在此示例中为SolrAutoConfiguration)方面遇到了一些困难.为了说明我设置了一个简化的例子:
https://github.com/timtebeek/componentscan-exclusions
实际上,有大约20多个内部@SpringBootApplication项目,每个项目都有自己的依赖项.(不理想/不是我的想法,但现在很难离开.)
问题出现是因为多个子项目正在使用Solr 5.2.1,但Spring Boot仅与4.x兼容.在最终的应用程序中(示例中的module-b)我想@SpringBootApplication在所有模块中导入所有类,同时阻止SolrAutoConfiguration运行:
@ComponentScan("project") // Broad scan across all company jars
@SpringBootApplication(exclude = { SolrAutoConfiguration.class }) // Failing exclude
public class ModuleBApp {
public static void main(final String[] args) {
SpringApplication.run(ModuleBApp.class, args);
}
}
Run Code Online (Sandbox Code Playgroud)
这失败了,因为@SpringBootApplication通过@ComponentScan没有特定排除的任何实例仍然加载SolrAutoConfiguration.
在组合多个@SpringBootApplication类时,如何正确排除自动配置类?
我已经尝试过excludeFilters我的决赛@SpringBootApplication,但这还没有找到解决方案.
Spring引导提供@ComponentScan了查找要扫描的包.
我正在建立一个@RestControllers内部package com.mylib.controller有的库.还有其他类以及不同包中的构造型注释.
所以,如果有人正在使用com.myapp 基础包开发SpringBoot Application .他在他的应用程序中使用我的库.他需要提一下@ComponentScan("com.mylib")发现图书馆的刻板印象.
有没有办法扫描组件而不包括库包@ComponentScan?
由于spring-boot-starter-actuator暴露其端点只是依赖,没有定义@ComponentScan.或者无论应用程序基础包如何扫描的任何默认包.
dependency-injection spring-boot component-scan spring-boot-actuator spring-boot-starter
我在与配置类不同的包中有一个存储库,因此我使用@Repostiory 将其注释为以下内容:
package test;
@Repository
public interface UserTest extends JpaRepository<User, Long> {
}
Run Code Online (Sandbox Code Playgroud)
我已经对其进行了组件扫描,但没有奏效:
package com.app;
@SpringBootApplication
@ComponentScan({"test","com.app"})
public class Application extends SpringBootServletInitializer {
}
Run Code Online (Sandbox Code Playgroud)
例外:没有可用的“test.UserTest”类型的合格 bean:预期至少有 1 个 bean 有资格作为自动装配候选。
除非我添加 enableJpaRepositories ,否则为什么组件扫描不能在存储库上工作?我认为 componetScan 就足够了
更新:
由于某些答案提供了解决方案,我问的是解释而不是解决方案。以下内容甚至无需对“test”进行组件扫描即可工作:
SpringBootApplication
@EnableJpaRepositories({"test","com.app"})
public class Application extends SpringBootServletInitializer{
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是为什么我什至需要在 @Repository 上使用 componentscan 不起作用时?为什么在文档中@Repository 被componentscan 扫描时它没有效果并且@EnableJpaRepostiories 是enoguh?
来自关于组件扫描的 Spring 文档:指示是否应启用对使用 @Component @Repository、@Service 或 @Controller 注释的类的自动检测。
没有检测到我的@Repository
我有一个带有Spring容器的项目.假设调用此项目my-common-library并使用命名空间my.common.它扫描此命名空间中的所有组件,common-context.xml如下所示
<beans ...>
<context:component-scan base-package="my.common"/>
</beans>
Run Code Online (Sandbox Code Playgroud)
除此之外,此扫描还会检测带注释的类@MyComponent.
现在我想尽可能完全重用这个项目.假设我开始my-client在命名空间中使用的新项目my.client.该my-client大多由带注释的组件@MyComponent.
在理想世界中,我只想添加依赖关系my-common-library,所有@MyComponents都将被扫描和注册.唯一的问题是新的命名空间原始未知my-common-library.
一个解决方案,我所知道的是添加一个更新common-context.xml到my-client其看起来像
<beans ...>
<context:component-scan base-package="my.common,my.client"/>
</beans>
Run Code Online (Sandbox Code Playgroud)
这当然会奏效,但似乎非常脆弱.是否有更优雅的解决方案?
我有两个项目 A 和 B。两者都是用 Maven 构建的,项目 A 有一个对项目 B 的 Maven 依赖。这两个项目都有一个带有 @Configuration 注释的类,我在其中定义了 @Beans。
我在项目 A 中有来自两个项目的 bean。如果我在同一项目中定义的 bean 的项目 A 中使用 @Autowired 注释,则自动装配工作。但是,如果我在项目 B 的 bean 的项目 A 中使用 @Autowired 批注,则会出现异常。
这是什么意思?如何在项目 B 中定义的项目 A 中自动装配 bean?
@ComponentScan( //CS1\n basePackages = {"com.package.A", "com.package.B"},\n excludeFilters = @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,\n value = {com.Package.A.SomeClass.class\n })\n)\n\n@ComponentScan( //CS2\n basePackages = { "com.package.A"}\n)\n@EnableAutoConfiguration\n@SpringBootApplication\npublic class Application {\n public static void main(String[] args) throws Exception {\n ConfigurableApplicationContext ctx = SpringApplication.run(Application.class, args);\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n上面是我的SpringBootApplication主要课程。正如你所看到的,我必须使用 Annnotation,而不是 xml。有两个@ComponentScanAnnotation,当然Spring是不允许的。对我来说,这两种不同@ComponentScan意味着两种不同的方式来启动我的应用程序。如果我选择使用 CS1(这意味着 @ComponentScan1),我必须注释 CS2\xef\xbc\x8can,反之亦然。
它不优雅,不优雅。尤其是对于那些 Spring 新手。所以我想知道如何根据我的.properties文件动态配置它。例如我的.properties文件中名为“isScanA”的参数是true,那么我可以使用CS1。或者任何其他优雅的方式。
\n\n我已经尝试了很多。
\n\n使用占位符。例如@ComponentScan(basePackage="${scan.basePackage}")。并在需要时更改.properties文件中的值。但这种方法无法修复excludeFilters。因为如果我用来FilterType.ASSIGNABLE_TYPE分配需要排除的类,则value应该是Class类型而不是String,如果value = {"${scan.excludeClass}"}使用的话。
在 Spring boot 1.5.9 应用程序中,我有@SpringBootApplication一个主类。
我也有@KopaxgroupApi注释,其中:
@Retention(RUNTIME)
@Target(TYPE)
@Import(KopaxgroupApiConfig.class)
public @interface KopaxgroupApi {
@AliasFor(annotation = Import.class, attribute = "value")
Class<?>[] value() default { KopaxgroupApiConfig.class };
}
Run Code Online (Sandbox Code Playgroud)
与KopaxgroupApiConfig.class是:
@Configuration
@ComponentScan(basePackages = { KopaxgroupApiConfig.CLASSPATH })
public class KopaxgroupApiConfig {
public static final String CLASSPATH = "com.kopaxgroup.api";
}
Run Code Online (Sandbox Code Playgroud)
我在其中创建了一个新项目,com.kopaxgroup.api.customerManagement.callMeBack并且将存储库和服务分别存储在目录repository和中service。
找不到.CallMeBackServiceImplCallMeBackRepository
我在启动时遇到以下错误:
Application failed to start due to an exception
org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.kopaxgroup.api.customerManagement.callMeBack.repository.CallMeBackRepository' available: expected …Run Code Online (Sandbox Code Playgroud) component-scan ×13
java ×9
spring ×8
spring-boot ×8
autowired ×2
classpath ×1
fongo ×1
inheritance ×1
solr ×1
spring-junit ×1
spring-mvc ×1
webapp2 ×1