2. Hello World II (Bean Factory)



Each time you request a bean that implements the FactoryBean interface, the Spring IoC container will use this factory bean to create the target bean and return it to you. (Note: If you are sure that you want to get the factory bean instance itself, you can use the bean name preceded by &.)




A factory bean is very similar to a factory method, but it is a Spring-specific bean that can be identified by the Spring IoC container during bean construction.

So far we have been using Application Context (ClassPathXmlApplicationContext) to create beans, we could do the same using Bean Factory as here:


Bean Factory



Make a Java project in eclipse.
make a lib/ folder in the root of the project
Unzip spring-framework-3.1.0.M1.zip
from ./dist/ directory you will need
org.springframework.asm-3.1.0.M1.jar
org.springframework.beans-3.1.0.M1.jar
org.springframework.context-3.1.0.M1.jar
org.springframework.core-3.1.0.M1.jar
org.springframework.expression-3.1.0.M1.jar
from ./projects/spring-build/lib/ivy/
commons-logging.jar

Copy these to the lib/ folder you just made, add all of them as jar files to eclipse class path.


Make a bean class and the relevant bean.xml file as declared in 1. Hello World II

-------------------

To create a bean factory you have to implement FactoryBean interface. For convenience Spring provides an implementation in AbstractFactoryBean which provides the basic functionality. Other factory beans are mostly used to implement framework facilities, such as
JndiObjectFactoryBean:  When looking up an object (such as a data source) from JNDI
ProxyFactoryBean: When using classic Spring AOP to create a proxy for a bean
LocalSessionFactoryBean:  When creating a Hibernate session factory in the IoC container

Note: As a framework user, you seldom have to write custom factory beans, because they are framework-specific and cannot be used outside the scope of the Spring IoC container. Actually, you are always able to implement an equivalent factory method for a factory bean.


Example

package com.apress.springrecipes.shop;

public abstract class Product {
    private String name;
    private double price;

    public Product() {   }

    public Product(String name, double price) {    this.name = name;      this.price = price;    }

    public String toString() {       return name + " " + price;      }

    public String getName() {       return name;    }

    public void setName(String name) {        this.name = name;    }

    public double getPrice() {        return price;    }

    public void setPrice(double price) {        this.price = price;    }
}

-----------------
package com.apress.springrecipes.shop;
 
public class Battery extends Product {
 
    private boolean rechargeable;
 
    public Battery() {         super();     }
 
    public Battery(String name, double price) {         super(name, price);     }

    public boolean isRechargeable() {        return rechargeable;    }

    public void setRechargeable(boolean rechargeable) {        this.rechargeable = rechargeable;    }
}

-----------------
package com.apress.springrecipes.shop;

public class Disc extends Product {
    private int capacity;

    public Disc() {        super();    }

    public Disc(String name, double price) {        super(name, price);    }

    public int getCapacity() {        return capacity;    }

    public void setCapacity(int capacity) {        this.capacity = capacity;    }
}

-----------------
package com.apress.springrecipes.shop;

import org.springframework.beans.factory.config.AbstractFactoryBean;

public class DiscountFactoryBean extends AbstractFactoryBean {

    private Product product;
    private double discount;

    public void setProduct(Product product) {
        this.product = product;
    }

    @Override
    protected Object createInstance() throws Exception {
        product.setPrice(product.getPrice() * (1 - discount));
        return product;
    }

    @Override
    public Class getObjectType() {   //You have to return the target bean’s type in the getObjectType() method for the auto-wiring feature to work properly.
        return product.getClass();
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }
}


bean.xml
<beans ...>
    <bean id="factoriedaaa"
        class="com.apress.springrecipes.shop.DiscountFactoryBean">
        <property name="product">
            <bean class="com.apress.springrecipes.shop.Battery">
                <constructor-arg value="AAA" />
                <constructor-arg value="2.5" />
            </bean>
        </property>
        <property name="discount" value="0.2" />
    </bean>
 
    <bean id="factoriedcdrw"
        class="com.apress.springrecipes.shop.DiscountFactoryBean">
        <property name="product">
            <bean class="com.apress.springrecipes.shop.Disc">
                <constructor-arg value="CD-RW" />
                <constructor-arg value="1.5" />
            </bean>
        </property>
        <property name="discount" value="0.1" />
    </bean>
</beans>

This bean is equivalent in functionality to
DiscountFactoryBean aaa = new DiscountFactoryBean();
aaa.setProduct(new Battery("AAA", 2.5));
aaa.setDiscount(0.2);
Product aaa = (Product) aaa.createInstance();
 
DiscountFactoryBean cdrw = new DiscountFactoryBean();
cdrw.setProduct(new Disc("CD-RW", 1.5));
cdrw.setDiscount(0.1);
Product cdrw = (Product) cdrw.createInstance();

needs sample to code to execute, ?????

---------------------------------------------------------------------------------------------------------------------------------

Note: When using the basic collection tags to define collections, you can’t specify the concrete class of a collection, such as LinkedList, TreeSet, or TreeMap. Moreover, you cannot share a collection among different beans by defining it as a stand-alone bean for other beans to refer to.
Solution:
1. corresponding collection factory beans like ListFactoryBean, SetFactoryBean, and MapFactoryBean.
A factory bean is a special kind of Spring bean that is used for creating another bean.
2. The second option is to use collection tags such as <util:list>, <util:set>, and <util:map> in the util schema introduced in Spring 2.x.




You can use a collection factory bean to define a collection and specify its target class.


Checking Properties with Dependency Checking
You simply have to specify the dependency checking mode in the dependency-check attribute of <bean>.  but can’t check if their value is not null.
Dependency Checking Modes Supported by Spring
none: The default mode is none, but this can be changed by setting the default-dependency-check attribute of the <beans> root element.
simple:  If any properties of the simple types (the primitive and collection types) have not been set, an UnsatisfiedDependencyException will be thrown.
objects:   If any properties of the object types (other than the simple types) have not been set, an UnsatisfiedDependencyException will be thrown.
all: If any properties of any type have not been set, an UnsatisfiedDependencyException will be thrown.
* The default mode is none, but this can be changed by setting the default-dependency-check attribute of
the <beans> root element.
<bean id="sequenceGenerator"
    class="com.apress.springrecipes.sequence.SequenceGenerator"
    dependency-check="simple">
    <property name="initial" value="100000" />
    <property name="prefixGenerator" ref="datePrefixGenerator" />
</bean>

@Required

RequiredAnnotationBeanPostProcessor is a Spring bean post processor that checks if all the bean properties with the @Required annotation have been set. 
bean post processor is a special kind of Spring bean that is able to perform additional tasks on each bean before its initialization.
you must register it
can’t check if their value is not null.
 annotate their setter methods with @Required.
public class SequenceGenerator {
    private PrefixGenerator prefixGenerator;
    private String suffix;
    ...
    @Required
    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
        this.prefixGenerator = prefixGenerator;
    }
    @Required
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
    ...
}

To ask Spring to check if these properties have been set on all sequence generator instances, you have to register a RequiredAnnotationBeanPostProcessor instance in the IoC container. If you are using a bean factory, you have to register this bean post processor through the API. Otherwise, you can just declare an instance of this bean post processor in your application context.
<bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor" />
OR
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    <context:annotation-config />
    ...
</beans>


you can even declare and use your custom annotations.
package com.apress.springrecipes.sequence;
...
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Mandatory {
}
-----
public class SequenceGenerator {
 
    private PrefixGenerator prefixGenerator;
    private String suffix;
    ...
    @Mandatory
    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
        this.prefixGenerator = prefixGenerator;
    }
 
    @Mandatory
    public void setSuffix(String suffix) {
        this.suffix = suffix;
    }
    ...
}


To check for the properties with this annotation type, you have to specify it in the
requiredAnnotationType property of RequiredAnnotationBeanPostProcessor.
 
<bean class="org.springframework.beans.factory.annotation.
    RequiredAnnotationBeanPostProcessor">
    <property name="requiredAnnotationType">
        <value>com.apress.springrecipes.sequence.Mandatory</value>
    </property>
</bean>

Autowiring


Instead of wiring by explicitly specifying the references, container can use autowiring.
autowire attribute of <bean>
no: No auto-wiring will be performed. You must wire the dependencies explicitly.
byname:  For each bean property, wire a bean with the same name as the property.
bytype:  For each bean property, wire a bean whose type is compatible with that of the property. If more than one bean is found, an UnsatisfiedDependencyException will be thrown.
constructor: For each argument of each constructor, first find a bean whose type is compatible with the argument’s. Then, pick the constructor with the most matching arguments. In case of any ambiguity, an UnsatisfiedDependencyException will be thrown.
autodetect:  If a default constructor with no argument is found, the dependencies will be auto-wired by type. Otherwise, they will be auto-wired by constructor.

WILL REDUCE READABILITY
 we recommend applying autowiring only in applications whose component dependencies are not complicated.

 seen, if Spring finds more than one candidate bean for auto-wiring, it will throw an UnsatisfiedDependencyException. On the other hand, if the auto-wiring mode is set to byName or byType, and Spring cannot find a matching bean to wire, it will leave the property unset, which may cause a NullPointerException or a value that has not been initialized. However, if you want to be notified when auto-wiring cannot wire your beans, you should set the dependency-check attribute to objects or all. 

If you have a bean whose type is compatible with PrefixGenerator defined in the IoC container, it will be set to the prefixGenerator property automatically.
package com.apress.springrecipes.sequence;
 
import org.springframework.beans.factory.annotation.Autowired;
 
public class SequenceGenerator {
    ...
    @Autowired
    public void setPrefixGenerator(PrefixGenerator prefixGenerator) {
        this.prefixGenerator = prefixGenerator;
    }
}

----
import org.springframework.beans.factory.annotation.Autowired;
 
public class SequenceGenerator {
 
    @Autowired
    private PrefixGenerator[] prefixGenerators;
    ...
}

 
If you have multiple beans whose type is compatible with the PrefixGenerator defined in the IoC
container, they will be added to the prefixGenerators array automatically.

@Qualifier

Auto-Wiring by Type with Qualifiers

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
 
public class SequenceGenerator {
 
    @Autowired
    @Qualifier("datePrefixGenerator")
    private PrefixGenerator prefixGenerator;
    ...
}


Autowire by name you can annotate a setter method, a constructor, or a field with the JSR-250 @Resource

To use the JSR-250 annotations, you have to include the JSR 250 dependency. If you are using Maven, add:
<dependency>
   <groupId>javax.annotation</groupId>
   <artifactId>jsr250-api</artifactId>
   <version>1.0</version>
</dependency>



















Comments