spring 源碼解讀與設計詳解:3 FactoryBean,springfactorybean
上一篇文章講到BeanFactory,BeanFactory是實現spring IOC原理實現的根介面,而本篇所講的FactoryBean則是AOP原理實現的重要介面。
本文相關代碼:http://download.csdn.net/detail/sundenskyqq/8460579
1. 先看FactoryBean的源碼:
public interface FactoryBean<T> {T getObject() throws Exception;Class<?> getObjectType();boolean isSingleton();}
2. 下面簡單講一下FactoryBean相關概念。
Spring中有兩種類型的Bean,一種是普通Bean,另一種是工廠Bean,即FactoryBean,這兩種Bean都被容器管理,但工廠Bean跟普通Bean不同,其返回的對象不是該factoryBean的一個執行個體,其返回的是該FactoryBean的getObject方法所返回的對象。如果要擷取FactoryBean對象,可以在id前面加一個&符號來擷取。 在Spring架構內部,有很多地方有FactoryBean的實作類別,它們在很多應用如(Spring的AOP、ORM、交易管理)及與其它第三架構(ehCache)整合時都有體現。
Spring 架構中有很多FactoryBean 例如RmiProxyFactoryBean, SqlMapClientFactoryBean. LocalSessionFactoryBean等都是通過FactoryBean getObject方法驅動起來的.對bean的生產 修飾做了很好的封裝。
3. 用幾個例子來說明FactoryBean與普通bean的區別。
(1)普通bean
代碼:
package spring.factorybean;/** * @author Ding Chengyun * 2015-2-26 */public interface PersonService {public String getName();public String sayHello();public void setName(String name);}<pre name="code" class="java">package spring.factorybean;/** * @author Ding Chengyun * 2015-2-26 */public class PersonServiceImpl implements PersonService {public String name;/* (non-Javadoc) * @see spring.PersonService#getName() */@Overridepublic String getName() {return name;}/* (non-Javadoc) * @see spring.PersonService#sayHello() */@Overridepublic String sayHello() {System.out.println("sayHello");return "sayHello";}/* (non-Javadoc) * @see spring.PersonService#setName() */@Overridepublic void setName(String name) {this.name = name;}}
設定檔
<bean id="personService" class="spring.factorybean.PersonServiceImpl"><property name="name"><value>hello world</value></property></bean>
測試代碼:
@Test public void test02() { try {PersonService ps = context.getBean("personService", PersonService.class); ps.sayHello(); String name = ps.getName(); System.out.println(name);} catch (Exception e) {e.printStackTrace();} }
(2)FactoryBean
代碼:
package spring.factorybean;import org.springframework.beans.factory.FactoryBean;/** * @author Ding Chengyun * 2015-2-27 */public class MyFactoryBean implements FactoryBean<MyFactoryBeanImpl> {@Overridepublic MyFactoryBeanImpl getObject() throws Exception {return new MyFactoryBeanImpl();}@Overridepublic Class<?> getObjectType() {return MyFactoryBeanImpl.class;}@Overridepublic boolean isSingleton() {return false;}}<pre name="code" class="java">package spring.factorybean;/** * @author Ding Chengyun * 2015-2-27 */public class MyFactoryBeanImpl {}
設定檔
<bean id="myFactoryBean" class="spring.factorybean.MyFactoryBean"></bean>
測試代碼:
@Test public void test04() { try {MyFactoryBeanImpl bean = context.getBean("myFactoryBean", MyFactoryBeanImpl.class); System.out.println(bean); MyFactoryBean factoryBean = context.getBean("&myFactoryBean", MyFactoryBean.class); System.out.println(factoryBean); bean = (MyFactoryBeanImpl) factoryBean.getObject(); System.out.println(bean); } catch (Exception e) {e.printStackTrace();} }
4. 自訂一個FactoryBean,用來代理一個對象,對該對象的所有方法做一個攔截,在方法調用前後都輸出一行log.
代碼:
package spring.factorybean;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.FactoryBean;import org.springframework.beans.factory.InitializingBean;/** * @author Ding Chengyun * 2015-2-27 */public class MyLogFactoryBean implements FactoryBean<Object>, InitializingBean,DisposableBean {// 被代理對象實現的介面名(在使用Proxy時需要用到,用於決定產生的代理物件類型) private String interfaceName; // 被代理的對象 private Object target; // 產生的代理對象 private Object proxyObj; @Overridepublic void destroy() throws Exception { System.out.println("distory..."); }@Overridepublic void afterPropertiesSet() throws Exception {proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(),new Class[] { Class.forName(interfaceName) },new InvocationHandler() {public Object invoke(Object proxy, Method method,Object[] args) throws Throwable {System.out.println("method:" + method.getName());System.out.println("Method before...");Object result = method.invoke(target, args);System.out.println("Method after...");return result;}});}@Overridepublic Object getObject() throws Exception { return proxyObj; }@Overridepublic Class<?> getObjectType() {return proxyObj == null ? Object.class : proxyObj.getClass(); }@Overridepublic boolean isSingleton() {return false;}public String getInterfaceName() { return interfaceName; } public void setInterfaceName(String interfaceName) { this.interfaceName = interfaceName; } public Object getTarget() { return target; } public void setTarget(Object target) { this.target = target; } }設定檔
<bean id="myLogFactoryBean" class="spring.factorybean.MyLogFactoryBean"> <property name="interfaceName" value="spring.factorybean.PersonService" /> <property name="target" ref="personService"/> </bean>
測試代碼:
@Test public void test05() { PersonService ps = context.getBean("myLogFactoryBean", PersonService.class); ps.sayHello(); // String name = ps.getName(); // System.out.println(name); }