Java 如何管理FactoryBean spring创建的bean?
可以使用以编程方式创建可能需要复杂实例化逻辑的对象 但是,Java 如何管理FactoryBean spring创建的bean?,java,spring,autowired,Java,Spring,Autowired,可以使用以编程方式创建可能需要复杂实例化逻辑的对象 但是,FactoryBean创建的bean似乎没有成为spring管理的。这个解释正确吗?如果有,有什么好的解决办法吗?包含一个简短的代码示例来说明我的问题 应用程序上下文: <bean id="searcher" class="some.package.SearcherFactory" /> <bean id="service" class="some.package.Service" /> 手动方式是: 在工厂
FactoryBean
创建的bean似乎没有成为spring管理的。这个解释正确吗?如果有,有什么好的解决办法吗?包含一个简短的代码示例来说明我的问题
应用程序上下文:
<bean id="searcher" class="some.package.SearcherFactory" />
<bean id="service" class="some.package.Service" />
手动方式是:
ApplicationContext
注入工厂bean(或者通过实现ApplicationContextAware
获得),并执行ctx.getAutowireCapableBeanFactory().autowireBean(bean)
不过,我承认两人都感到奇怪
但事实上,如果逻辑如此简单(仅实例化),请使用
prototype
范围。由FactoryBean
创建的对象由Spring管理,而不是由Spring实例化或配置。通过使用FactoryBean
,您自己承担责任。所有注入和配置必须由FactoryBean处理
有一种可能更适合你的替代方法——使用。这意味着您可以在Java中使用复杂的实例化逻辑,同时仍然在对象本身上使用类似于@Autowired
的东西
我现在倾向于为所有非平凡的Spring应用程序使用注释样式配置,它使许多事情变得更加简单。这里是一个抽象的FactoryBean
实现,它为您实现自动连接:
public abstract class AbstractAutowiringFactoryBean<T> extends
AbstractFactoryBean<T> implements ApplicationContextAware{
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(
final ApplicationContext applicationContext){
this.applicationContext = applicationContext;
}
@Override
protected final T createInstance() throws Exception{
final T instance = doCreateInstance();
if(instance != null){
applicationContext
.getAutowireCapableBeanFactory()
.autowireBean(instance);
}
return instance;
}
/**
* Create the bean instance.
*
* @see #createInstance()
*/
protected abstract T doCreateInstance();
}
公共抽象类AbstractAutowiringFactoryBean扩展
AbstractFactoryBean实现ApplicationContextAware{
私有应用程序上下文应用程序上下文;
@凌驾
public void setApplicationContext(
最终应用程序上下文(应用程序上下文){
this.applicationContext=applicationContext;
}
@凌驾
受保护的最终T createInstance()引发异常{
final T instance=doCreateInstance();
if(实例!=null){
应用程序上下文
.getAutowireCapableBeanFactory()的
.autowireBean(实例);
}
返回实例;
}
/**
*创建bean实例。
*
*@see#createInstance()
*/
受保护的抽象T doCreateInstance();
}
扩展它,实现getObjectType()
和doCreateInstance()
方法,就可以启动并运行自动连接了
注意:不应用BeanPostProcessor,这需要额外的代码。这怎么办
<bean id="serviceFactory"
class="some.package.SearcherFactory" />
<bean id="service"
factory-bean="serviceFactory"
factory-method="getObject"/>
。。。然后只注入bean“服务”,而不关心代码中的工厂FactoryBean是一个接口,作为开发人员,您在编写工厂类时实现了该接口,您希望工厂类创建的对象通过Spring作为bean进行管理,而另一方面,BeanFactory,表示SpringIOC容器,它包含托管bean并提供检索它们的访问。它是实现控制反转容器基本功能的框架核心的一部分
File: context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sha" class="MessageDigestFactoryBean">
<property name="algorithm" value="SHA1"/>
</bean>
<bean id="md5" class="MessageDigestFactoryBean"/>
</beans>
File: Main.java
import java.security.MessageDigest;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
String d1 = (String) factory.getBean("sha");
String d2 = (String) factory.getBean("md5");
System.out.println(d1);
System.out.println(d2);
}
}
class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
private static final String DEFAULT_ALGORITHM = "MD5";
private String algorithm = DEFAULT_ALGORITHM;
public Object getObject() throws Exception {
return this.algorithm;
}
public Class getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public void afterPropertiesSet() throws Exception {
this.algorithm += " after setting";
}
}
在大多数情况下,除非扩展框架的核心功能,否则您不会直接使用或实现BeanFactory接口。当您有工厂创建的对象需要由Spring管理时,您可以实现FactoryBean
简而言之,BeanFactory表示Spring容器,而FactoryBean表示工厂类,其创建的对象被拾取并注册为容器中的bean
File: context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sha" class="MessageDigestFactoryBean">
<property name="algorithm" value="SHA1"/>
</bean>
<bean id="md5" class="MessageDigestFactoryBean"/>
</beans>
File: Main.java
import java.security.MessageDigest;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
String d1 = (String) factory.getBean("sha");
String d2 = (String) factory.getBean("md5");
System.out.println(d1);
System.out.println(d2);
}
}
class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
private static final String DEFAULT_ALGORITHM = "MD5";
private String algorithm = DEFAULT_ALGORITHM;
public Object getObject() throws Exception {
return this.algorithm;
}
public Class getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public void afterPropertiesSet() throws Exception {
this.algorithm += " after setting";
}
}
文件:context.xml
文件:Main.java
导入java.security.MessageDigest;
导入org.springframework.beans.factory.FactoryBean;
导入org.springframework.beans.factory.initializebean;
导入org.springframework.beans.factory.xml.XmlBeanFactory;
导入org.springframework.core.io.ClassPathResource;
公共班机{
公共静态void main(字符串[]args){
XmlBeanFactory factory=newxmlbeanfactory(newclasspathResource(“context.xml”);
字符串d1=(字符串)factory.getBean(“sha”);
字符串d2=(字符串)factory.getBean(“md5”);
系统输出打印项次(d1);
系统输出打印项次(d2);
}
}
类MessageDigestFactoryBean实现FactoryBean,初始化Bean{
私有静态最终字符串DEFAULT_ALGORITHM=“MD5”;
私有字符串算法=默认的_算法;
公共对象getObject()引发异常{
返回此参数。算法;
}
公共类getObjectType(){
返回MessageDigest.class;
}
公共布尔isSingleton(){
返回true;
}
公共void集合算法(字符串算法){
这个算法=算法;
}
public void afterPropertieSet()引发异常{
该算法+=“设置后”;
}
}
它可以工作,并且至少可以将弹簧联轴器降低到单个工厂级别。+1。我刚刚开始使用基于注释的配置来处理这些类型的场景。那么,您将如何解决作者提出的问题呢?您能用适当的java配置更新答案吗?这也不是一个坏主意,可以提高可重用性。虽然我想知道为什么springsource的朋友们还没有将其作为模板提供。尝试了这一个,导致stacktrace出现问题,getObject()方法不存在。根据这个链接:一个service.getObject().getObject()将被调用。评论员并不打算照本宣科地复制上面的内容。在本例中,您的SearchFactory类型需要实现一个方法,如getObject(),该方法将返回所需类型的对象,或者您可以根据需要命名该方法。
File: context.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="sha" class="MessageDigestFactoryBean">
<property name="algorithm" value="SHA1"/>
</bean>
<bean id="md5" class="MessageDigestFactoryBean"/>
</beans>
File: Main.java
import java.security.MessageDigest;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
XmlBeanFactory factory = new XmlBeanFactory(new ClassPathResource("context.xml"));
String d1 = (String) factory.getBean("sha");
String d2 = (String) factory.getBean("md5");
System.out.println(d1);
System.out.println(d2);
}
}
class MessageDigestFactoryBean implements FactoryBean, InitializingBean {
private static final String DEFAULT_ALGORITHM = "MD5";
private String algorithm = DEFAULT_ALGORITHM;
public Object getObject() throws Exception {
return this.algorithm;
}
public Class getObjectType() {
return MessageDigest.class;
}
public boolean isSingleton() {
return true;
}
public void setAlgorithm(String algorithm) {
this.algorithm = algorithm;
}
public void afterPropertiesSet() throws Exception {
this.algorithm += " after setting";
}
}