Java – write a simple spring example using play! skeleton

I'm trying to make spring 1.0 1 module is set to use with play! 1.2. one

First, I add the spring module to the dependencies yml:

- play -> spring 1.0.1

Then I according to application The document in conf adds the following content:

play.spring.component-scan=true

Then I run the following code to download the dependencies and update my IntelliJ configuration:

play deps --sync
play idealize

Now when I go back to IntelliJ, I can see spring-1.0 1 has been added to the list of project modules that look correct to me However, if I look at the dependencies of my project, it is not located in spring-1.0 1 / jar in lib directory If I try to annotate one of my classes with @ component, it won't find it However, if I manually add spring-1.0 1 / lib as a project dependency, it will find @ component very good Do I want to run something else to let my IntelliJ project identify the spring Library in the module?

The second part of my question involves connecting a simple example and writing tests for it

So, suppose I have a job class like this:

@Component
@Every("10min")
public class MyJob extends Job {
    private @Inject Printer printer;

    @Override
    public void doJob() throws Exception {
        printer.print();
    }
}

The printer class looks like this:

@Component
public class Printer {
    public void print() {
        System.out.println("foo");
    }
}

First, does the comment look correct? Second, I'll how to write a program that can call myjob Dojob() test, but inject a different printer that prints "bar" instead of "foo"?

Update: as mentioned by Aaron, I changed @ inject to @ Autowired In my test class, I have such things:

@Test
public void testSomething() {
    MyJob job = play.modules.spring.Spring.getBeanOfType(MyJob.class);
    job.doJob();
    ...
}

It failed on the getbeanoftype statement with the following:

play.modules.spring.SpringException
at play.modules.spring.Spring.getBean(Spring.java:11)
at com.testing.JobTest.testSomething(MyJob.java:20)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at play.test.PlayJUnitRunner$startPlay$1$1$1.execute(PlayJUnitRunner.java:73)
at play.Invoker$Invocation.run(Invoker.java:265)
at play.Invoker.invokeInThread(Invoker.java:67)
at play.test.PlayJUnitRunner$startPlay$1$1.evaluate(PlayJUnitRunner.java:68)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at play.test.PlayJUnitRunner.run(PlayJUnitRunner.java:48)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:60)

Update 2: OK, I really get more now It seems that even if I'm scanning for components, the spring module still needs application context in the conf / directory XML (even if it does not define beans)

Now I just need to figure out how to inject different versions of printer objects, which will spit out "bar" instead of "foo"

Update 3: I have replaced @ resource (name = "printer") with @ Autowired, annotated my production printer with @ component ("printer"), renamed it realprinter, and provided an interface:

@Component("printer")
public class RealPrinter implements Printer {
    public void print() {
        System.out.println("foo");
    }
}

If I only have the above printer, the injection will work normally Now, if I create a testprinter, I need the spring module of play to implement it. I want to use testprinter instead of realprinter when executing the test class

@Component("printer")
public class TestPrinter implements Printer {
    public void print() {
        System.out.println("bar");
    }
}

However, because I have two components named "printer", the spring module of play will throw the following exception:

play.exceptions.UnexpectedException: Unexpected Error
at play.Play.start(Play.java:491)
at play.test.PlayJUnitRunner.<init>(PlayJUnitRunner.java:31)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at org.junit.internal.builders.AnnotatedBuilder.buildrunner(AnnotatedBuilder.java:31)
at org.junit.internal.builders.AnnotatedBuilder.runnerForClass(AnnotatedBuilder.java:24)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.builders.AllDefaultPossibilitiesBuilder.runnerForClass(AllDefaultPossibilitiesBuilder.java:29)
at org.junit.runners.model.RunnerBuilder.safeRunnerForClass(RunnerBuilder.java:57)
at org.junit.internal.requests.ClassRequest.getRunner(ClassRequest.java:24)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:66)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:192)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:60)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:115)
Caused by: java.lang.IllegalStateException: Annotation-specified bean name 'printer' for bean class [com.testing.job.RealPrinter] conflicts with existing,non-compatible bean deFinition of same name and class [com.testing.job.TestPrinter]
at org.springframework.context.annotation.ClassPathBeanDeFinitionScanner.checkCandidate(ClassPathBeanDeFinitionScanner.java:267)
at org.springframework.context.annotation.ClassPathBeanDeFinitionScanner.doScan(ClassPathBeanDeFinitionScanner.java:208)
at org.springframework.context.annotation.ClassPathBeanDeFinitionScanner.scan(ClassPathBeanDeFinitionScanner.java:180)
at play.modules.spring.SpringPlugin.onApplicationStart(SpringPlugin.java:98)
at play.plugins.PluginCollection.onApplicationStart(PluginCollection.java:408)
at play.Play.start(Play.java:463)
... 19 more

As you can see, the reason for the exception is that there are now two printers with the same name

Solution

OK, I've come up with a solution that suits me Therefore, in order to write a simulation / test version of the injected bean, I did the following:

@Test
public void testSomething() {
    GenericApplicationContext context = SpringPlugin.applicationContext;
    GenericBeanDeFinition deFinition = new GenericBeanDeFinition();
    deFinition.setBeanClass(TestPrinter.class);
    deFinition.setAutowireCandidate(true);
    context.registerBeanDeFinition("printer",deFinition);

    MyJob job = new MyJob();
    job.doJob();
}

Then I had to change myjob to become the "injection" of what it needed:

public class MyJob extends Job {
    public void doJob() throws Exception {
        Printer printer = Spring.getBeanOfType(Printer.class);
        printer.print();
    }
}

Testprinter no longer needs to annotate with @ component, because the test method is to register the test printer bean programmatically to overwrite the production printer bean

Therefore, executing the testsomething () method will result in "bar" printing If I delete the registerbeandefinition thing, it will cause the generated "foo" message to be printed

I'm not sure if this is the cleanest way to inject test content using play's spring module, but at least I can do what I want

The content of this article comes from the network collection of netizens. It is used as a learning reference. The copyright belongs to the original author.
THE END
分享
二维码
< <上一篇
下一篇>>