And now, children, watch in awe as I instantiate these four objects:
In general, it's probably not hugely useful to have Configured create all your objects (as we are doing here), as Spring is full of good stuff such as transaction management and bean lifecycle events that you can hook into, and it would be a shame to lose out on all of that.
Consequently, although Configured has a standard rule for auto-instantiating objects with a certain type or super-type, this feature is mainly intended for saving you from having to deal with helper-type objects which the main beans in your application delegate to (e.g. transformers etc).
Configured is most useful when you use its Service Providers feature in conjunction with Spring's Components feature. That said, this article serves as a basic introduction to Configured, so we're not dealing with that here, just getting it to build a very basic object graph.
Notice that this bean graph contains a cyclic reference and also that it's probably not very relevant to the real world. I'll write a better example one day; for now, just try to imagine that we're wiring some Web Service class with auto-instantiated and configured DAO's and a MediatingCommandExecutorFactoryObserver, if that helps you get it up.
Below is the application context definition we're going to use, we've defined 4 rules, which get evaluated in order of their configured precedence
Also, the ignoredDependencyTypes property on BeanGraphAutowiringServiceImpl tells it to never attempt to autowire the given properties if it encounters them.
<!-- snippet --> <bean id="autowiringService" class="net.sourceforge.configured.spring.factory.SpringSimpleBeanGraphAutowiringServiceFactory"> <property name="rulebase"> <set> <bean class="net.sourceforge.configured.rules.standard.InstantiationRule"> <property name="intantiatedTypes"> <set> <value>net.sourceforge.configured.spring.TestClassA</value> <value>net.sourceforge.configured.spring.TestClassB</value> <value>net.sourceforge.configured.spring.TestClassD</value> </set> </property> <property name="precedence" value="2" /> </bean> <bean class="net.sourceforge.configured.spring.rules.RetrieveFromApplicationContextByNameRule"> <property name="precedence" value="3" /> </bean> <bean class="net.sourceforge.configured.spring.rules.RetrieveFromApplicationContextByTypeRule"> <property name="precedence" value="4" /> </bean> </set> </property> <property name="ignoredDependencyTypes"> <set> <value>org.springframework.context.ApplicationContext</value> </set> </property> </bean> <bean id="message" class="java.lang.String" > <constructor-arg value="Hello World" /> </bean> <bean id="c" class="net.sourceforge.configured.spring.TestClassC"> </bean> <bean class="net.sourceforge.configured.spring.InjectByRulesAnnotationPostProcessor"> <property name="autowiringService" ref="autowiringService" /> </bean> <!-- end snippet -->
And now here's the relevant bits of code, first the actual objects getting wired (with getters and setters omitted, although by default only fields with getters and setters are wired)
Notice that TestClassD has no annotations and will be instantiated by the InstantiationRule because it is included in that bean's ignoredDependencyTypes Set.
TestClassC is defined as @ConfiguredByRules and will be returned from the application context by the RetrieveFromApplicationContextByNameRule as it's missing from the ignoredDependencyTypes Set.
TestClassB is annotated to cause the message property to be ignored by the rulebase, TestClassB will be instantiated by the InstantiationRule as per TestClassD.
TestClassA has the @ConfiguredByRules annotation... and will also be instantiated by the InstantiationRule.
@ConfiguredByRules public class TestClassA { private TestClassB b; private TestClassD d; private String message; // getters and setters omitted... } @FieldsIgnoredByBeanRules(ignoredFields="message") public class TestClassB { private TestClassD d; private String message; // getters and setters omitted... } @ConfiguredByRules public class TestClassC { private TestClassA a; private String message; // getters and setters omitted... } public class TestClassD { private TestClassC c; // getters and setters omitted... }
And now, at last, here's our test code, I'm using the SpringJUnit4ClassRunner to auto-doofer all that tedious Spring stuff. Good times.
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations={"/testContext.xml"}) @ConfiguredByRules public class ExampleTestCase { private TestClassA testClassA; @Test public void doTest() { Assert.assertNotNull(testClassA); // assert that TestClassC had it's message property resolved from the application context Assert.assertEquals("Hello World", testClassA.getD().getC().getMessage()); // assert that this really is a cyclic graph Assert.assertTrue(testClassA.getB() == testClassA.getD().getC().getA().getB()); } // getters and setters omitted... }
This page has introduced the basics of Configured, however we've glossed over how to get Configured to know how to wire concrete classes to dependencies on interface definitions, which is dealt with in the section: Service Providers , and in addition how you can define separate sets of rules to wire up logically distinct parts of your application, which is dealt with in the section: Rulebase Modules .