博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Spring 源码学习(2) —— FactoryBean 的使用
阅读量:4571 次
发布时间:2019-06-08

本文共 4886 字,大约阅读时间需要 16 分钟。

一般情况下, Spring是通过反射机制利用bean的class属性指定实现类来完成实例化bean的。在某些特定的情况下, 想做一些定制,Spring为此提供了一个org.springframework.beans.factory.FactoryBean的工厂类接口, 用户可以通过实现该接口定制实例化bean的逻辑。

Spring从3.0开始, FactoryBean开始支持泛型, 即接口声明改为: FactoryBean<T> 的形式。

1 package org.springframework.beans.factory; 2  3 public interface FactoryBean
{ 4 5 /** 6 * 7 * @return 返回由FactoryBean创建的bean实例, 如果isSingleton()返回true, 则该实例则会放到Spring容器单实例缓存池中 8 * @throws Exception 9 */10 T getObject() throws Exception;11 12 /**13 *14 * @return 返回FactoryBean创建Bean的类型15 */16 Class
getObjectType();17 18 /**19 *20 * @return 返回有FactoryBean创建的bean实例的作用域是singleten还是prototype21 */22 boolean isSingleton();23 }

 

 

Action

创建一个pojo类<Car>。

1 /** 2  * @filename: Car.java 3  * @author: Wang Chinda 4  * @date: 2018-05-22 5  * @version: v1.0 6  * @modify_history: - 7  * 20180522   Wang Chinda   create 8  * 20180522   Wang Chinda   modify   method() 9  */10 package com.itdoc.learn.source.factory;11 12 /**13  * @desc FactoryBean 的使用14  * @author Wang Chinda15  * @create 2018-05-22 16:0716  */17 public class Car {18     /** 最大速度 */19     private int maxSpeed;20     /** 品牌 */21     private String brand;22     /** 价钱 */23     private double price;24 25     public int getMaxSpeed() {26         return maxSpeed;27     }28 29     public void setMaxSpeed(int maxSpeed) {30         this.maxSpeed = maxSpeed;31     }32 33     public String getBrand() {34         return brand;35     }36 37     public void setBrand(String brand) {38         this.brand = brand;39     }40 41     public double getPrice() {42         return price;43     }44 45     public void setPrice(double price) {46         this.price = price;47     }48 49     @Override50     public String toString() {51         return "Car{" +52                 "maxSpeed=" + maxSpeed +53                 ", brand='" + brand + '\'' +54                 ", price=" + price +55                 '}';56     }57 }

 

创建一个定制实例化bean逻辑的类<CarFactoryBean>:

1 /** 2  * @filename: CarFactoryBean.java 3  * @author: Wang Chinda 4  * @date: 2018-05-22 5  * @version: v1.0 6  * @modify_history: - 7  * 20180522   Wang Chinda   create 8  * 20180522   Wang Chinda   modify   method() 9  */10 package com.itdoc.learn.source.factory;11 12 import org.springframework.beans.factory.FactoryBean;13 14 /**15  * @desc FactoryBean测试的工厂类16  * @author Wang Chinda17  * @create 2018-05-22 16:1718  */19 public class CarFactoryBean implements FactoryBean
{20 21 /** 车的详细信息 */22 private String carInfo;23 24 @Override25 public Car getObject() throws Exception {26 Car car = new Car();27 String[] infos = carInfo.split(",");28 car.setBrand(infos[0].trim());29 car.setMaxSpeed(Integer.valueOf(infos[1].trim()));30 car.setPrice(Double.valueOf(infos[2].trim()));31 return car;32 }33 34 @Override35 public Class
getObjectType() {36 return Car.class;37 }38 39 @Override40 public boolean isSingleton() {41 return false;42 }43 44 public String getCarInfo() {45 return carInfo;46 }47 48 public void setCarInfo(String carInfo) {49 this.carInfo = carInfo;50 }51 }

 

配置xml<car-factory-bean.xml>:

1 
2
5 6 7
8
9
10 11

 

测试<Car>:

1 /** 2  * @filename: CarClient.java 3  * @author: Wang Chinda 4  * @date: 2018-05-22 5  * @version: v1.0 6  * @modify_history: - 7  * 20180522   Wang Chinda   create 8  * 20180522   Wang Chinda   modify   method() 9  */10 package com.itdoc.learn.source.factory;11 12 import org.springframework.context.ApplicationContext;13 import org.springframework.context.support.ClassPathXmlApplicationContext;14 15 /**16  * @desc FactoryBean使用测试客户端入口17  * @author Wang Chinda18  * @create 2018-05-22 16:2719  */20 public class CarClient {21     public static void main(String[] args) {22         ApplicationContext applicationContext = new ClassPathXmlApplicationContext("test/car-factory-bean.xml");23         Car car = (Car) applicationContext.getBean("car");24         System.out.println(car);25     }26 }

 

控制台打印:

 

 

流程分析:

当配置文件中<bean>的class属性配置类的实现类是FactoryBean时, 通过getBean返回的不是FactoryBean本身, 而是FactoryBean#getObject()方法返回的对象, 相当于FactoryBean#getObject()代理了getBean()方法。

从缓存中或者singletonFactories中的ObjectFactory中获取共享实例。

Object sharedInstance = getSingleton(beanName);

bean = getObjectForBeanInstance(sharedInstance, name, beanName, mbd); 获取对应实例。

 

强制将共享实例转化成FactoryBean。FactoryBean<?> factory = (FactoryBean<?>) beanInstance;

object = getObjectFromFactoryBean(factory, beanName, !synthetic); 在FactoryBean中获取bean实例。

doGetObjectFromFactoryBean(factory, beanName, shouldPostProcess);

调用getObject()方法,object = factory.getObject();

 

返回实例bean。

 

GitHub源码: 

 

转载于:https://www.cnblogs.com/goodcheap/p/9073287.html

你可能感兴趣的文章
LINQ用法总结
查看>>
【web开发】docker中的数据库
查看>>
Python“Non-ASCII character 'xe5' in file”报错问题(转)
查看>>
正则 取出url中的数值
查看>>
js:正则表达
查看>>
redis初识
查看>>
P1303 A*B Problem
查看>>
Web交互中Json的应用案例
查看>>
mysql生成日期的辅助表
查看>>
122A
查看>>
时间复杂度为O(nlogn)的LIS算法
查看>>
Java核心_Git_Maven学习[20181108]
查看>>
Python3 的递归
查看>>
jquery判断页面网址是否有效
查看>>
OC 的Runtime 消息转发机制
查看>>
单线程与多线程的简单示例(以Windows服务发短信为示例)
查看>>
Redis在win7上的可视化应用
查看>>
Linq表连接大全(INNER JOIN、LEFT OUTER JOIN、RIGHT OUTER JOIN、FULL OUTER JOIN、CROSS JOIN)
查看>>
微信小程序之转发功能(附效果图和源码)
查看>>
成熟法则
查看>>