BeanFactory 与 FactoryBean的区别
1. BeanFactory
BeanFacotry是spring中比较原始的Factory。如XMLBeanFactory就是一种典型的BeanFactory。
原始的BeanFactory无法支持spring的许多插件,如AOP功能、Web应用等。
ApplicationContext接口,它由BeanFactory接口派生而来,ApplicationContext包含BeanFactory的所有功能,
通常建议比BeanFactory优先
常见:xmlBeanFactory (从spring 3.1版本后,xmlBeanFactory被表明为Deprecated.
推荐使用DefaultListableBeanFactory和XmlBeanDefinitionReader替换)
2. FactoryBean
以Bean结尾,表示它是一个Bean,不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,
根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,
如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
为什么使用FactoryBean : 一般情况下,Spring通过反射机制利用<bean>的class属性指定实现类实例化Bean,在某些情况下,
实例化Bean过程比较复杂,如果按照传统的方式,则需要在<bean>中提供大量的配置信息。配置方式的灵活性是受限的,
这时采用编码的方式可能会得到一个简单的方案。
Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制
实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,
Spring自身就提供了70多个FactoryBean的实现.
SqlSessionFactoryBean , MapperFactoryBean 。
package com.springcloud.beanTest;
import com.springcloud.MybatisApplication;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Import;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Auther:ok168
* @Date: 2019/4/24 16:44
* @Description:
*/
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = {MybatisApplication.class})
@Slf4j
@Import(FactoryBeanTest2.class)
public class FactoryBeanTest{
@Autowired
private ApplicationContext context;
@Test
public void test(){
FactoryBeanTest2 factoryBeanTest2= (FactoryBeanTest2)context.getBean(FactoryBeanTest2.class);
log.info("myBean = " + factoryBeanTest2.getObject() );
MyBeanService myBean = (MyBeanService) factoryBeanTest2.getObject();
myBean.sayHello("hello,我是factoryBeanTest2.getObject得到的!");
MyBeanService myBean2= (MyBeanService)context.getBean(MyBeanService.class);
myBean2.sayHello("hello,我是context.getBean得到的!");
}
}
@Slf4j
class FactoryBeanTest2 implements FactoryBean<Object> , InitializingBean {
//接口类
private String interfaceName = "com.springcloud.beanTest.MyBeanService";
//bean
private Object target = new MyBean();
//代理类对象
private Object proxyObj;
@Override
public Object getObject(){
return proxyObj;
}
@Override
public Class<?> getObjectType() {
return proxyObj == null ? Object.class : proxyObj.getClass();
}
// 模仿ProxyFactoryBean的功能
@Override
public void afterPropertiesSet() throws Exception {
// require interface
proxyObj = Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Class.forName(interfaceName)} , new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("invoke method before......" + System.currentTimeMillis());
Object result = method.invoke(target, args);
log.info("invoke method after......" + System.currentTimeMillis());
return result;
}
});
log.info("proxyObj = " + proxyObj );
}
}
interface MyBeanService{
public void sayHello(String msg);
}
class MyBean implements MyBeanService{
@Override
public void sayHello(String msg){
System.out.println(StringUtils.defaultIfEmpty(msg , "msg是空的!"));
}
}
PS : @Slf4j注解 安装lombok插件 : https://www.cnblogs.com/shindo/p/7550790.html