Bean Configuration Using Java - Annotation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
@Configuration
public class AppConfig
{
@Value ("Mike" ) String personName;
@Bean (name='Chinese' )
public Person person (){
Chinese p = new Chinese();
p.setAxe(stoneAxe());
p.setName(personName());
return p;
}
@Bean (name="stoneAxe" )
public Axe stoneAxe (){
return new StoneAxe();
}
}
Other Annotations
@Import
: define a java config class. This is used to import other java config classes to current java config class
@Scope
: Define bean’s life scope for current method
@Lazy
: Define if current method’s bean need to be delay-initialize or not
@DependOn
: Define a bean that needs to be initialized before current method’s bean
Make XML Load Java Config:
1
2
3
4
5
<beans.... >
<context:annotation-config />
<bean class ="org.crazyit.app.config.AppConfig" />
</beans >
Make Java Load XML Config:
1
2
3
4
5
6
7
@Configuration
@ImportResource ("classpath:/bean.xml" )
public class MyConfig
{
...
}
Bean Instance Creation and Dependency Configuration
Three ways to create bean instance:
Use Constructor
Use Static Factory
Use Instance Factory
Use Constructor:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public interface Person {
public void useAxe ();
}
public class Chinese implements Person {
public Axe axe;
public Chinese (){
System.out.print("Spring initialize Chinese instance" );
}
public void setAxe (Axe axe){
System.out.println("Spring is injecting dependency..." );
this .axe = axe;
}
public void useAxe (){
System.out.println(axe.chop());
}
}
public interface Axe
{
public String chop ();
}
public class SteelAxe implements Axe
{
public SteelAxe (){
System.out.println("Spring initialize SteelAxe instance" );
}
public String chop (){
return "Chop Method" ;
}
}
1
2
3
4
5
6
7
8
<beans ... >
<bean id ="chinese" class ="org.crazyit.app.service.impl.Chinese" >
<property name ="axe" ref ="steelAxe" />
</bean >
<bean id ="steelAxe" class ="org.crazyit.app.serivce.impl.SteelAxe" />
</beans >
1
2
3
4
5
6
7
8
9
10
11
public static void main (String[] args){
ApplicationContext ctx = new ClassPathApplicationContext("bean.xml" );
Person p = ctx.getBean("Chinese" , Person.class);
p.useAxe();
}
Spring initialize SteelAxe instance
Spring is injecting dependency...
Chop Method
*/
Use Static Factory:
Static factory class and factory-method needs to be defined first. Method must be static
.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
public interface Being {
public void testBeing ();
}
public class Dog implements Being {
private String msg;
public void setMsg (String msg){
this .msg = msg;
}
public void testBeing (){
System.out.println(msg+ "Dog test for interface method " );
}
}
public class Cat implements Being
{
private String msg;
this .msg = msg;
}
public void testBeing (){
System.out.println(msg + "Cat test for interface method" );
}
}
public class BeingFatory () {
Get static factory method for being instance. arg decides the parameter to choose which being method
*/
public static Being getBeing (String arg){
if (arg.equalsIgnoreCase("dog" )){
return new Dog();
}
else {
return new cat();
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<bean id ="dog" class ="org.crazyit.app.factory.BeingFacory" factory-method ="getBeing" >
<constructor-arg value ="dog" />
<property name ="msg" value ="I'm a dog" />
</bean >
<bean id ="cat" class ="org.crazyit.app.factory.BeingFacory" factory-method ="getBeing" >
<constructor-arg value ="cat" />
<property name ="msg" value ="I'm a cat" />
</bean >
1
2
3
4
5
6
7
public static void main (String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml" );
Being b1 = ctx.getBean("dog" , Being.class);
b1.testBeing();
Being b2 = ctx.getBean("cat" , Being.class);
b2.testBeing();
}
Use Instance Facory:
No need to add class when config bean, because Spring don’t need to instant bean anymore, Spring just use the method that can inistant bean.
Bean configuration for instance factory needs to have two attributes:
factory-bean: Bean id for factory bean
factory-method: Define method for instance factory
1
2
3
4
5
6
7
8
9
10
<bean id ="beingFactory" class ="org.crazyit.app.factory.PersonFactory" />
<bean id ="cat" factory-bean ="BeingFactory" factory-method ="getBeing" >
<constructor-arg value ="cat" >
</bean >
<bean id ="dog" factory-bean ="BeingFactory" factory-method ="getBeing" >
<constructor-arg value ="dog" />
</bean >
Abstract Bean
Abstract bean will not be initialized . Abstract bean always work as a parent bean that can be inheriented.
1
2
3
4
5
6
<bean id ="steelAxe" class ="org.carzyit.app.service.impl.SteelAxe" >
<bean id ="chineseTemplate" abstruct = "true ">
<property name ="axe" ref ="steelAxe" />
</bean >
</bean >
Child Bean
If lots of beans have similar config, a bean template can be created, then child bean can inherent config info from this bean template. If child bean has different info as parent bean, child bean will overwrite parent bean config.
Following config cannot be inheriented :
Depends-on
Autowire
Scope
lazy-init
1
2
3
4
5
6
7
<bean id ="chineseTemplate" class ="org.crazyit.app.service.impl.Chinese" abstract ="true" >
<propery name ="axe" ref ="steelAxe" >
</bean >
<bean id ="chinese" parent ="chineseTemplate" >
<property name ="axe" ref ="stoneAxe" >
</bean >
Get Bean Id
User setBeanName(String name)
in BeanNameAware
interface:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class Chinese implements BeanNameAware
{
private String beanName;
public void setBeanName (String name){
this .beanName = name;
}
public void info (){
System.out.println(beanName);
}
}
public void static main (String[] args){
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml" );
Chinese chin = ctx.getBean("chinese" , Chinese.class);
chin.info();
}
Give a bean attributes from other beans
1
2
3
4
5
6
<bean id ="son2" class ="org.crazyit.app.service.Son" >
<property name ="age" >
<bean id ="person.son.age" class ="org.springframework.beans.factory.config.PropertyPathFactoryBean" />
</property >
</bean >