作用
我理解的FactoryBean类似于Spring容器向外开放了一个途径,可以供开发者把想要自己创建对象放入Spring容器里,供后续使用
FactoryBean 的主要方法
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
boolean isSingleton();
}
将需要放入Spring容器的对象写在getObject
例子
1 简单放个String对象
public class FactoryBean2 implements FactoryBean<String> {
@Override
public String getObject() throws Exception {
System.out.println("我new 了一个String对象");
return "1" ;
}
@Override
public Class<?> getObjectType() {
return null;
// return String.class;
}
@Override
public boolean isSingleton() {
return false;
}
}
配置:
<bean name = "s" class="com.*.FactoryBean2"/>
获取Bean使用
@Resource
String s;
@Test
public void testFs(){
System.out.println(s);
}
2 生成一个接口的对象
@Data
public class MyBean<T> implements FactoryBean<T> , InitializingBean {
private String interFaceName;
@Override
public T getObject() throws Exception {
Consumer consumer = new Consumer();
consumer.setInterFaceName(interFaceName);
Enhancer enhancer = new Enhancer();
enhancer.setInterfaces(new Class[]{Class.forName(interFaceName)});
enhancer.setCallback(new MethodInterceptor() {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
consumer.refer((String)args[0],method.getName());
return null;
}
});
T proxy = (T)enhancer.create();
/* Class clz = ClassUtils.getClass(interFaceName);
System.out.println(clz.isInterface());
T proxy = (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{clz},(Object o, Method m,Object[] args)->{
System.out.println("我用了一个代理,"+m.getName()+","+args[0]);
return null;
});*/
return proxy;
}
@Override
public Class<?> getObjectType() {
return null;
/* Class<T> tClass = (Class<T>)((ParameterizedType)getClass().
getGenericSuperclass()).getActualTypeArguments()[0];
return tClass;*/
}
@Override
public boolean isSingleton() {
return false;
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("我想要设置一个Bean");
}
public interface InterfaceA {
String a(String p);
void b(String b);
}
配置
<bean name = "bean1" class="com.*.MyBean">
<property name="interFaceName" value="com.*.InterfaceA"/>
</bean>
获取Bean并使用:
@Resource
InterfaceA bean1;
@Test
public void testRegister() {
bean1.a("dasd");
}
分析
为什么会获取到FactoryBean中返回的对像呢
org.springframework.beans.factory.support.StaticListableBeanFactory#getBean(java.lang.String)
String beanName = BeanFactoryUtils.transformedBeanName(name);
Object bean = this.beans.get(beanName);
if (bean == null) {
throw new NoSuchBeanDefinitionException(beanName,
"Defined beans are [" + StringUtils.collectionToCommaDelimitedString(this.beans.keySet()) + "]");
}
// Don't let calling code try to dereference the
// bean factory if the bean isn't a factory
if (BeanFactoryUtils.isFactoryDereference(name) && !(bean instanceof FactoryBean)) {
throw new BeanIsNotAFactoryException(beanName, bean.getClass());
}
if (bean instanceof FactoryBean && !BeanFactoryUtils.isFactoryDereference(name)) {
try {
return ((FactoryBean<?>) bean).getObject();
}
catch (Exception ex) {
throw new BeanCreationException(beanName, "FactoryBean threw exception on object creation", ex);
}
}
else {
return bean;
}
}