TechRoad_book_Spring_Professional
goal : architecture foundation
2020-06-13
FactoryBean p100
创建不能通过使用new 运算符创建的bean, 例如通过静态工厂方法访问的bean,Factory bean 是一个bean, 可以作为其他bean的工厂,
当 Spring 使用 FactoryBean 接口来满足依赖或查找请求时,它并不返回 FactoryBean; 相反,调用 FactoryBean 的 getObject() 返回调用结果.
效果很好,最明显的用途时创建事务代理,以及从 JNDI 上下文中自动获取资源。
FactoryBean 不仅仅用于构建Spring的内部组件,当构建自己的应用程序时也是非常有用的,因为允许通过使用 IoC来管理更多的资源。
示例:
MessageDigest 本身时抽象的,通过调用 MessageDigest.getInstance() 并传入想要使用的摘要算法的名称来获得具体的实现。
例如: MessageDigest md5 = MessageDigest.getInstance("MD5");
在用 Spring 来管理 MessageDigest 对象的创建
1. 不用 FactoryBean, 最好的方法时使用 bean 上的属性 algorithm, 然后初始化回调来调用 MessageDigest.getInstance();
2.(推荐) 使用 FactoryBean, 将相关逻辑封装在一个 bean 中,然后需要 MessagedDigest 实例的任何bean都可以简单地声明属性messageDigest, 并使用 FactoryBean 来获取实例。
package org.example.cp4_FactoryBean; import com.sun.xml.internal.ws.client.dispatch.MessageDispatch; import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.InitializingBean; import java.security.MessageDigest; public class MessageDigestFactoryBean implements FactoryBean<MessageDigest>, InitializingBean { private String algorithmName = "MD5"; private MessageDigest messageDigest = null; @Override public MessageDigest getObject() throws Exception{ return messageDigest; } @Override public Class<MessageDigest> getObjectType(){ return MessageDigest.class; } @Override public boolean isSingleton(){ return true; } @Override public void afterPropertiesSet() throws Exception{ messageDigest = MessageDigest.getInstance(algorithmName); } public void setAlgorithmName(String algorithmName){ this.algorithmName = algorithmName; } }
Spring 调用 getObject() 方法来检索由 FactoryBean 创建的对象, 该对象被传递给使用 FactoryBean 作为协作者的其他bean,
MessageDigestFactoryBean 传递了一个在 InitializingBean.afterPropertiesSet() 回调中创建的用于创建 MessageDigest实例的副本。
getObjectType() 方法允许告诉 Spring FactoryBean 所返回对象的类型。
如事先不知道返回类型,例如 FactoryBean 根据配置创建不同类型的对象,只有在初始化后才能确定,则对象类型可以为 null,
但如果指定了类型, Spring可以使用该类型实现自动装配。
也可以尝试返回一个接口并让 FactoryBean实例化具体的实现类,但除非有必要。
不知道返回的具体类型,但所有的bean都会使用 MessageDigest 来定义它们的依赖项。
isSingleton() true 可以告诉 Spring FactoryBean 的单例状态,而不是所返回的对象。
package org.example.cp4_FactoryBean; import java.security.MessageDigest; public class MessageDigester { private MessageDigest digest1; private MessageDigest digest2; public void setDigest1(MessageDigest digest1){ this.digest1 = digest1; } public void setDigest2(MessageDigest digest2){ this.digest2 = digest2; } public void digest(String msg){ System.out.println("Using digest1"); digest(msg,digest1); System.out.println("Using digest2"); digest(msg, digest2); } private void digest(String msg, MessageDigest digest){ System.out.println("Using algorithm: " + digest.getAlgorithm()); digest.reset(); byte[] bytes = msg.getBytes(); byte[] out = digest.digest(bytes); System.out.println(out); } }




场景: 实例化由非 Spring 的第三方应用程序所提供的 JavaBean,可能不知道如何实例化该类,但直到 第三方应用程序提供了一个可用于获取 Spring app 所需的 JavaBean 实例的类,该场景下 可使用 <bean> 标记中的factory-bean 和 factory-method 属性。
1 package org.example.cp4_FactoryBean; 2 3 import java.security.MessageDigest; 4 5 public class MessageDigestFactory { 6 private String algorithmName = "MD5"; 7 8 public MessageDigest createInstance() throws Exception{ 9 return MessageDigest.getInstance(algorithmName); 10 } 11 12 public void setAlgorithmName(String algorithmName){ 13 this.algorithmName = algorithmName; 14 } 15 }
1 <?xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> 5 6 <bean id="shaDigestFactory" 7 class="org.example.cp4_FactoryBean.MessageDigestFactory" 8 p:algorithmName="SHA1"/> 9 <bean id="defaultDigestFactory" 10 class="org.example.cp4_FactoryBean.MessageDigestFactory"/> 11 12 <bean id="shaDigest" 13 factory-bean="shaDigestFactory" 14 factory-method="createInstance"> 15 </bean> 16 17 <bean id="defaultDigest" 18 factory-bean="defaultDigestFactory" 19 factory-method="createInstance"> 20 </bean> 21 22 <bean id="digester" 23 class="org.example.cp4_FactoryBean.MessageDigester" 24 p:digest1-ref="shaDigest" 25 p:digest2-ref="defaultDigest"> 26 </bean> 27 </beans>
1 package org.example.cp4_FactoryBean; 2 3 import org.springframework.context.support.GenericXmlApplicationContext; 4 5 public class MessageDigestFactoryMethodDemo { 6 public static void main(String... args){ 7 GenericXmlApplicationContext ctx = new GenericXmlApplicationContext(); 8 ctx.load("classpath:Spring/cp4_factoryBeanMethod.xml"); 9 ctx.refresh(); 10 11 MessageDigester digester = ctx.getBean("digester",MessageDigester.class); 12 digester.digest("Hello World!"); 13 14 ctx.close(); 15 } 16 }


浙公网安备 33010602011771号