MicroSpring |
| Home |
Before starting on MicroSpring it was important to gather notes on 'best practice' and 'minimum practice' for IOC in Spring. These notes are below, often directly cut and pasted from the Spring 1.1.3 help text. This works as a small guide on using the Spring Framework. It also formed the ground work for the Micro Spring implementation.
Do not bother reading it, unless you are really bored. Instead look at the one page crib sheet.
All taken from the spring documentation at:
<install dir>\spring-framework-1.1.3\docs\reference\html_single\index.html
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans> <bean id="exampleBean" class="examples.ExampleBean"> <property name="beanOne"><ref bean="anotherExampleBean"/></property> <property name="beanTwo"><ref bean="yetAnotherBean"/></property> <property name="integerProperty"><value>1</value></property> <property name="url"><value>http://foo/</value></property> </bean>
<bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
<bean id="exampleStaticFuncInit" class="examples.ExampleStaticInit" factory-method="createInstance"> <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg> <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg> <constructor-arg><value>1</value></constructor-arg> </bean> </beans>
public class ExampleBean {
private AnotherBean beanOne;
private YetAnotherBean beanTwo;
private int i;
private String url;
public void setBeanOne(AnotherBean beanOne) {
this.beanOne = beanOne;
}
public void setBeanTwo(YetAnotherBean beanTwo) {
this.beanTwo = beanTwo;
}
public void setIntegerProperty(int i) {
this.i = i;
}
public void setUrl(String url) {
this.url = url;
}
}
public class ExampleStaticInit {
private ExampleStaticInit () {
}
public static ExampleStaticInit createInstance(
AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {
ExampleBean eb = new ExampleBean();
return eb;
}
}
IOC is OK, kinda works, but does create stupid chinese walls in your code. But, why not. Given that attitude, why not use spring as its this years fasion in Java Land (much like Jboss was 2 or 3 years ago). However, only a cut down, simple spring, and not the entire “run time, heavy framework, retrain all your staff”, environment.
Or to put it another way, what I want from spring is IOC. If I want something for ORM or AOP or resource bundles or event propogation I will use something else small and light. I do not believe in making XML config files contain complex logic and config which is better placed in a database or java code.
Transaction management – loads of java gurus recon that it is terribly hard and your average developer is an idiot so their framework will do it all for you through an xml(read deployment ascii) file. I disagree. When I write code and look at code I want the behaviour to be within the code, and to be explicit. So again, I discard springs transactional AOPtastic, embedded meta data approach. Likewise their jdbc implementation – it may have some good stuff in, but it is not the standard, and requires training. Database access is not hard, there is no need to protect folks from it.
Web frameworks. I don’t believe in springs new kid on the block/encapsulate the world mantra. Web apps are no longer nearly as important as they were – Fit Clients are back. Lots of choices are out there, so choose one – JSF or Struts seem good and are still modern.
In summary, spring encourages you to pick and choose from its services, and I have. IOC and that’s it.
InputStream is = new FileInputStream("beans.xml");
XmlBeanFactory factory = new XmlBeanFactory(is);
boolean containsBean(String) Object getBean(String) throws BeansException; Object getBean(String,Class) throws BeansException; boolean isSingleton(String) throws NoSuchBeanDefinitionException Class getType(String name) throws NoSuchBeanDefinitionException; String[] getAliases(String) throws NoSuchBeanDefinitionException;
Most people using Spring prefer to have actual JavaBeans (having just a default (no-argument) constructor and appropriate setters and getters modelled after the properties) in the BeanFactory
setter-based dependency injection is realized by calling setters on your beans after invoking a no-argument constructor or no-argument static factory method to instantiate your bean. Beans defined in the BeanFactory that use setter-based dependency injection are true JavaBeans.
most users of Spring will not be dealing with these classes directly (i.e. programmatically), but rather with an XML definition file which will be converted internally into instances of these classes, and used to load an entire BeanFactory or ApplicationContext.
Null param value null = <property name="email"><null/></property>
Empty string value “” = <property name="email"></property>
The list, set, map, and props elements allow properties and arguments of Java
type List, Set, Map, and Properties, respectively, to be defined and set.
<property name="people"> <props> <prop key="HarryPotter">The magic property</prop> <prop key="JerrySeinfeld">The funny property</prop> </props> </property> <!-- results in a setSomeList(java.util.List) call --> <property name="someList"> <list> <value>a list element followed by a reference</value> <ref bean="myDataSource"/> </list> </property> <!-- results in a setSomeMap(java.util.Map) call --> <property name="someMap"> <map> <entry key="yup an entry"> <value>just some string</value> </entry> <entry key="yup a ref"> <ref bean="myDataSource"/> </entry> </map> </property> <!-- results in a setSomeSet(java.util.Set) call --> <property name="someSet"> <set> <value>just some string</value> <ref bean="myDataSource"/> </set> </property>
Note that the value of a Map entry, or a set value, can also again be any of
the elements:
(bean | ref | idref | list | set | map | props | value | null)
Every bean has one or more ids (also called identifiers, or names; these terms refer to the same thing). These ids must be unique within the BeanFactory or ApplicationContext the bean is hosted in.
…you use the id or name attributes to specify the bean id(s), and at least one id must be specified in one or both of these attributes. The id attribute allows you to specify one id, and as it is marked in the XML DTD (definition document) as a real XML element ID attribute, the parser is able to do some extra validation when other elements point back to this one. As such, it is the preferred way to specify a bean id.
An idref element is simply a shorthand and error-proof way to set a property
to the String id or name of another bean in the container.
Using the idref tag will allow Spring to validate at deployment time that the
other bean actually exists.
Additionally, if the bean being referred to is in the same actual XML file,
and the bean name is the bean id, the local attribute may be used, which will
allow the XML parser itself to validate the bean name even earlier, at XML document
parse time.
<property name="targetName"><idref local="theTargetBean"/></property>
For most users, the majority of the beans in the container will be singletons.
Beans are defined to be deployed in one of two modes: singleton or non-singleton.
...This potentially delayed visibility of some configuration issues is why ApplicationContext by default pre-instantiates singleton beans. At the cost of some upfront time and memory to create these beans before they are actually needed, you find out about configuration issues when the ApplicationContext is created, not later. If you wish, you can still override this default behavior and set any of these singleton beans to lazy-load (not be pre-instantiated).
The non-singleton, prototype mode of a bean deployment results in the creation of a new bean instance every time a request for that specific bean is done. This is ideal for situations where for example each user needs an independent user object or something similar.
Beans are deployed in singleton mode by default, unless you specify otherwise. Keep in mind that by changing the type to non-singleton (prototype), each request for a bean will result in a newly created bean and this might not be what you actually want. So only change the mode to prototype when absolutely necessary.
Note: when deploying a bean in the prototype mode, the lifecycle of the bean changes slightly. By definition, Spring cannot manage the complete lifecycle of a non-singleton/prototype bean, since after it is created, it is given to the client and the container does not keep track of it at all any longer.
Dependencies
1.The BeanFactory is created and initialized with a configuration which describes
all the beans.
2. Each bean has dependencies expressed in the form of properties, ….
These dependencies will be provided to the bean, when the bean is actually created.
3. Each property or constructor-arg is either an actual definition of the value
to set, or a reference to another bean in the BeanFactory.
4. Each property or constructor argument which is a value must be able to be
converted from whatever format it was specified in, to the actual type of that
property or constructor argument. (compex description in main docn, describes
all the lovely varients).
5. Bean configs are validated by spring, but only instatiated at creation time.
6. Spring will resolve dependancies (create beans) as late as possible. Can
lead to runtime exceptions if your beans are bad.
To make sure that there is a certain order of creation you can use the depends-on
attribute.
<bean id="beanOne" class="ExampleBean" depends-on="manager">
<property name="manager"><ref local="manager"/></property>
</bean>
<bean id="manager" class="ManagerBean"/>
Notes: beans with no class defn are parent beans by default, the abstract keywork means you are also specifying the base class impl. i.e. if no class name then not a problem, spring just treats the beans as a template.
A bean definition potentially contains a large amount of configuration information,
including container specific information (i.e. initialization method, static
factory method name, etc.) and constructor arguments and property values. A
child bean definition is a bean definition which inherits configuration data
from a parent definition. It is then able to override some values, or add others,
as needed. Using parent and child bean definitions can potentially save a lot
of typing.
<bean id="inheritedTestBean" abstract="true"
class="org.springframework.beans.TestBean">
<property name="name"><value>parent</value></property>
<property name="age"><value>1</value></property>
</bean>
<bean id="inheritsWithDifferentClass" class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBean" init-method="initialize">
<property name="name"><value>override</value></property>
<!-- age should inherit value of 1 from parent -->
</bean>
A child bean definition will use the bean class from the parent definition if
none is specified, but can also override it. In the latter case, the child bean
class must be compatible with the parent, i.e. it must accept the parent's property
values.
Important Note: Application contexts (but not simple bean factories) will by default pre-instantiate all singletons. Therefore it is important (at least for singleton beans) that if you have a (parent) bean definition which you intend to use only as a template, and this definition specifies a class, you must make sure to set the abstract attribute to true, otherwise the application context will actually pre-instantiate it.
Provided through the ApplicationEvent class and ApplicationListener interface. When deployed to an application context the bean will be notified of events - the standard Observer design pattern. Spring provides three standard events: