我目前正在明斯特大学准备我的学士学位论文。我计划自动识别 Spring 配置中的典型问题。市场上有很多工具可以执行静态代码分析以查找错误或问题。这些显然无法检测仅在运行时出现的问题。我将分析一个 Spring 应用程序的 ApplicationContext 并通过使用反射和 bean 图的分析来查找错误配置。
示例: 一个简单的示例是,如果有人想通过使用注释来使类或方法事务安全。他通常会在类或方法上方添加一个@Transactional-tag,但是如果应用程序没有正确配置并且没有注册到ApplicationContext 的事务管理器,它观察注解,那么该标记将被忽略。不会出现错误信息,这也是目前很难发现这类问题的原因。
问题: 使用弹簧机制的错误配置导致的最常见错误或架构故障是哪些,可以通过动态分析检测到?是否有任何项目参与做类似的事情?
PS在我的论文过程中,我将开发一个可以检测此类问题的原型,并在以后将其开源。:)
我有一个基于Spring Framework 4及其子项目 - Spring Data Solr 的项目。
我有机会看到的所有示例都解释了如何组织您的项目 - 从基本实体( pojo )类到 Spring 特定类(例如存储库和服务)。当谈到测试功能时,所有示例都显示带有私有字段( spring bean )的测试,该字段通常在注释的帮助下进行初始化
@ContextConfiguration(classes = some-spring-data-main-class.class, loader = SpringApplicationContextLoader.class)
Run Code Online (Sandbox Code Playgroud)
然后就可以在方法中调用它的bean的方法了@Test。
但是,当涉及到项目中的 init bean 时 - 如何使用 Spring 4 来实现它,它是完全无 XML 的(我的意思是,我没有文件applicationContext xml)。
PS 在 Spring 3 中我们通常这样写:
ApplicationContext context = new ClasspathApplicationContext("applicationContext.xml")
Run Code Online (Sandbox Code Playgroud)
期望与 Spring 4 类似的东西引入应用程序初始化的全新概念是否合理?现在我们应该写什么来初始化应用程序的第一个 bean?
我正在学习 Spring Core 认证,我发现一些与代理概念相关的疑问。
所以在学习材料上,我找到了以下测验:
有一个 Java配置类,其中包含以下方法:
@Bean
public AccountRepository accountRepository(){
return new JdbcAccountRepository();
}
@Bean
public TransferService transferService1() {
TransferServiceImpl service = new TransferServiceImpl();
service.setAccountRepository(accountRepository());
return service;
}
@Bean
public TransferService transferService2() {
return new TransferServiceImpl( new JdbcAccountRepository() );
}
Run Code Online (Sandbox Code Playgroud)
如您所见,transferService()有两种不同的实现,分别命名为transferService1()和transferService2(),它们创建并返回TransferServiceImpl对象。
第一个创建一个新的TransferServiceImpl对象,然后对其调用setAccountRepository()方法。
第二个只是创建一个TransferServiceImpl将一个新的JdbcAccountRepository对象传递给它的构造函数。
它问我**前两种方法的最佳实现是什么?
提供的答案是:首选调用专用方法。所以我认为它说最好的方法是第一个实现。
它解释说AccountRepository bean 是一个单例(因为它是 Spring 中 bean 的标准范围)但是JdbcAccountRepository()可以被调用两次或更多次(例如在前面的代码片段中,它在调用方法时被调用 …
java spring design-patterns proxy-pattern applicationcontext
我有两个 spring 应用程序上下文。一个是我的应用程序本地的,另一个来自 maven 依赖项之一。
现在,我的applicationContext.xml文件看起来像这样。
<import resource="classpath*:**/sample-applicationContext.xml" />
Run Code Online (Sandbox Code Playgroud)
我<context:component-scan>在sample-applicationContext.xml扫描组件的文件中。
现在,当我执行以下操作时..
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
MyClass m=ctx.getBean(MyClass.class);
Run Code Online (Sandbox Code Playgroud)
不幸的是,当我得到MyClass对象时,对象被创建,但是,我看到MyClass没有注入依赖项。
自动装配的依赖项MyClass是使用<context:component-scan>insample-applicationContext.xml文件扫描的 bean 。
有没有办法在我的项目类中使用 Maven 依赖项中存在的多个应用程序上下文并自动装配它们?
我正在使用 JSF + Spring+ Hibernate
protected @Inject ChartOfAccount chartOfAccount;
Run Code Online (Sandbox Code Playgroud)
chartOfAccount我基本上想从列表中填充
for (DistributionEntry de : getDistributionEntries()) {
chartOfAccount.setAccount(de.getAccount());
chartOfAccountList.add(chartOfAccount);
}
Run Code Online (Sandbox Code Playgroud)
对于每次迭代,我想要新的对象,chartOfAccount否则你知道列表包含具有最新值的相同对象。
解决方案一:使用 new 关键字 :-p
for (DistributionEntry de : getDistributionEntries()) {
ChartOfAccount coa= new ChartOfAccount();
coa.setAccount(de.getAccount());
chartOfAccountList.add(coa);
}
Run Code Online (Sandbox Code Playgroud)
解决方案二:applicationContext.getBean
for (DistributionEntry de : getDistributionEntries()) {
chartOfAccount= applicationContext.getBean(ChartOfAccount.class);
chartOfAccount.setAccount(de.getAccount());
chartOfAccountList.add(chartOfAccount);
}
Run Code Online (Sandbox Code Playgroud)
但我读过某些文章,以避免使用applicationContext.getBean
如果我避免使用applicationContext.getBean,处理这种情况的最佳方法是什么?两种行为都会相同吗?(ApplicationContext.getBean 与 new 关键字)
注意:我的托管bean是@Scope(“session”),模型是@Scope(BeanDefinition.SCOPE_PROTOTYPE),所以我们都知道,对于一个会话,它是单例,而不同会话的原型。
我正在尝试运行 mvnintegration-test阶段,但在执行集成测试时出现Failed to load ApplicationContext错误(单元测试正确执行)。我正在SpringJUnit4ClassRunner使用类来运行我的测试。
这是完整的堆栈跟踪:
2017-02-09 03:22:15.705 [main] ERROR o.s.t.context.TestContextManager - Caught exception while allowing TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@5c072e3f] to prepare test instance [com.dentilax.app.accountservice.AccountServiceIT@768b970c]
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:117)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:230)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.createTest(SpringJUnit4ClassRunner.java:228)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner$1.runReflectiveCall(SpringJUnit4ClassRunner.java:287)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.methodBlock(SpringJUnit4ClassRunner.java:289)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:247)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) …Run Code Online (Sandbox Code Playgroud) 我有 3 组测试:单元、集成、验收。
@RunWith(SpringRunner.class))当我运行“所有测试”时,会启动 2 个不同的应用程序上下文,并且我有重复的队列订阅者。
我知道此订阅者重复的以下解决方法:
在一组测试之后,是否有任何方便的方法来卸载应用程序上下文?
@DirtiesContext 是绝配spring.test.context.cache.maxSize=1 @RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@TestExecutionListeners({FlywayTestExecutionListener.class, DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
public abstract class AcceptanceTest {}
Run Code Online (Sandbox Code Playgroud) 例如,如果我在application-context.xml中声明:
<context:annotation-config/>
Run Code Online (Sandbox Code Playgroud)
我从官方文件中读到:
在隐式注册后处理器包括AutowiredAnnotationBeanPostProcessor,CommonAnnotationBeanPostProcessor会,PersistenceAnnotationBeanPostProcessor,以及上述RequiredAnnotationBeanPostProcessor.
但我想知道Spring是如何工作的,我认为这个1-liner被转换为文档中提到的后处理器的几个bean定义.
但是,我的问题是,哪个Spring组件/类实现了"从1-liner到多个bean定义的转换"功能?
java spring xml-namespaces post-processing applicationcontext
Spring表达式在PropertySource注释中不起作用.
@PropertySource({ "classpath:application.properties",
"#{systemProperties['user.home']}/.app.properties" })
@Configuration
public class Config {
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
PropertySourcesPlaceholderConfigurer result = new PropertySourcesPlaceholderConfigurer();
result.setOrder(0);
return result;
}
}
Run Code Online (Sandbox Code Playgroud) 我正在尝试提高我正在研究的项目的Spring集成测试的性能。我们正在使用Spring + Gradle + JUnit。
在build.gradle文件中使用以下配置:
test {
useJUnit()
setForkEvery(0)
setMaxParallelForks(1)
}
Run Code Online (Sandbox Code Playgroud)
我们能够在单个JVM中运行所有测试。虽然我认为这是默认行为。
但是我一直在阅读有关Spring Test Context Caching的内容,并且在我的application-test.yml中具有以下属性:
logging:
level:
org:
springframework:
test:
context:
cache: DEBUG
Run Code Online (Sandbox Code Playgroud)
我注意到以下日志用于同一类中运行的测试方法
2017-09-05 08:33:11.829 DEBUG 5764 --- [ Test worker] c.DefaultCacheAwareContextLoaderDelegate : Storing ApplicationContext in cache under key [THIS HAD SENSITIVE DATA]
2017-09-05 08:33:11.830 DEBUG 5764 --- [ Test worker] org.springframework.test.context.cache : Spring test ApplicationContext cache statistics: [DefaultContextCache@572e81e7 size = 1, maxSize = 32, parentContextCount = 0, hitCount = 0, missCount = …Run Code Online (Sandbox Code Playgroud) spring ×9
java ×6
junit ×2
maven ×2
annotations ×1
gradle ×1
javabeans ×1
jsf ×1
launch ×1
scope ×1
spring-boot ×1
spring-mvc ×1
spring-test ×1
testing ×1