Spring中 FactoryBean 的理解

FactoryBean通常是用来创建比较复杂的bean,一般的bean直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean和复杂的逻辑,用xml配置比较困难,这时可以考虑用的FactoryBean。

FactoryBean的接口  


package org.springframework.beans.factory;

public interface FactoryBean<T> {
    T getObject() throws Exception;

    Class<?> getObjectType();

    boolean isSingleton();
}

我们先看一下 FactoryBean 的应用案例 然后在对其进行分析和讲解 

很多开源项目在集成Spring时都使用到FactoryBean,比如MyBatis提供mybatis-spring项目中的org.mybatis.spring.SqlSessionFactoryBean

bean id="tradeSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="trade" />
        <property name="mapperLocations" value="classpath*:mapper/trade/*Mapper.xml" />
        <property name="configLocation" value="classpath:mybatis-config.xml" />
        <property name="typeAliasesPackage" value="com.bytebeats.mybatis3.domain.trade" />
    </bean>

org.mybatis.spring.SqlSessionFactoryBean 如下:

package org.mybatis.spring;

public class SqlSessionFactoryBean implements FactoryBean<SqlSessionFactory>, InitializingBean, ApplicationListener<ApplicationEvent> {
private static final Log LOGGER = LogFactory.getLog(SqlSessionFactoryBean.class);
        ......
}

另外,阿里开源的分布式服务框架Dubbo中的Consumer也使用到了FactoryBean:

public class ReferenceBean<T> extends ReferenceConfig<T> implements FactoryBean, ApplicationContextAware, InitializingBean, DisposableBean {

}

下面我们进行一个案例 来说明一下  FactoryBean的使用 

1  声明一个Person类 

package com.lqp.test.day02;

public class Person {
	
	public void say() {
		System.out.println("我 》。。");
	}
}

2 声明一个工厂类  继承 FactoryBean 的方法  

package com.lqp.test.day02;

import org.springframework.beans.factory.FactoryBean;

public class PersonFactory  implements FactoryBean<Person>{

	@Override
	public Person getObject() throws Exception {
		return new Person();  // 返回一个对象
	}

	@Override
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Person.class;  //返回一个类的类型
	}

	@Override
	public boolean isSingleton() {
		return true;  //是否是单例
	}
	

}

3 声明一个配置类     对PersonFactory  类 进行配置

package com.lqp.test.day02;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ConfigTest {
    //为PersonFactory 注册 
	//注意 这里的bean 存放的不是PersonFactory对象  而是 他里面的person对象
	@Bean
	public PersonFactory personFactory() {
		return new PersonFactory();
	}
}

4 测试类

package com.lqp.test.day02;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class TestConfig {

	@SuppressWarnings("resource")
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(ConfigTest.class);
	    Person bean = (Person)context.getBean("personFactory"); //获得的是 Person对象  
	    System.out.println(bean.getClass().getName()); //com.lqp.test.day02.Person
	    bean.say();  //我 》。。

	   
	   //因为PersonFactory 实现了 FactoryBean 的接口  所以他将不是普通的bean  
	     //如果将要获取它  那么就需要在  相应的 实现bean的name 前面加一个 & 符号  
	    Object bean2 = context.getBean("&personFactory") ; 
	    String name = bean2.getClass().getName();
	    System.out.println(name);    //com.lqp.test.day02.PersonFactory
	}
}

源码注释

由{@link BeanFactory}中使用的对象实现的接口
 这些都是工厂。如果bean实现了这个接口,
  它被用作公开的对象的工厂,而不是直接作为bean
 将暴露自己的实例。
 
 <p> <b>注意:实现此接口的bean不能用作普通bean。</ b> FactoryBean是以bean样式定义的,但是为bean引用公开的对象({@link #getObject()始终是它创建的对象。

  <p> FactoryBeans可以支持单例和原型,并且可以
  或者根据需要懒洋洋地创建对象,或者在启动时急切地创建对象。
 {@link SmartFactoryBean}接口允许公开
 更精细的行为元数据。
 
  <p>此接口在框架内部大量使用,用于
  AOP的例子{@link org.springframework.aop.framework.ProxyFactoryBean}
 或{@link org.springframework.jndi.JndiObjectFactoryBean}。
  它也可以用于应用程序组件;然而,
  这在基础设施代码之外并不常见。
 
 <P> <b>注意:</ b>的
 FactoryBean对象参与包含
  BeanFactory的bean创建同步。通常没有
  除了懒惰之外,还需要内部同步
  在FactoryBean本身(或类似)中初始化。

参考  https://www.jianshu.com/p/6f0a59623090

https://blog.csdn.net/zknxx/article/details/79572387

发布了19 篇原创文章 · 获赞 8 · 访问量 4134

猜你喜欢

转载自blog.csdn.net/paohui001lqp/article/details/97135890