spring刚启动时 会进入doGetBean方法,若是bean是首次建立,则会进入建立Bean的步骤java
先经过Factory建立对象spring
再调用getObjectForBeanInstance(sharedInstance, name, beanName, mbd)sql
getObjectForBeanInstance有三个判断 从上至下执行bash
一般状况下,bean 无须本身实现工厂模式,Spring 容器担任了工厂的 角色;但少数状况下,容器中的 bean 自己就是工厂,做用是产生其余 bean 实例。由工厂 bean 产生的其余 bean 实例,再也不由 Spring 容器产生,所以与普通 bean 的配置不一样,再也不须要提供 class 元素。mybatis
先定义一个Bean实现FactoryBean接口app
@Component
public class MyBean implements FactoryBean {
private String message;
public MyBean() {
this.message = "经过构造方法初始化实例";
}
@Override
public Object getObject() throws Exception {
// 这里并不必定要返回MyBean自身的实例,能够是其余任何对象的实例。
//如return new Student()...
return new MyBean("经过FactoryBean.getObject()建立实例");
}
@Override
public Class<?> getObjectType() {
return MyBean.class;
}
public String getMessage() {
return message;
}
}
复制代码
MyBean实现了FactoryBean接口的两个方法,getObject()是能够返回任何对象的实例的,这里测试就返回MyBean自身实例,且返回前给message字段赋值。同时在构造方法中也为message赋值。而后测试代码中先经过名称获取Bean实例,打印message的内容,再经过&+名称
获取实例并打印message内容。ide
@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class)
public class FactoryBeanTest {
@Autowired
private ApplicationContext context;
@Test
public void test() {
MyBean myBean1 = (MyBean) context.getBean("myBean");
System.out.println("myBean1 = " + myBean1.getMessage());
MyBean myBean2 = (MyBean) context.getBean("&myBean");
System.out.println("myBean2 = " + myBean2.getMessage());
System.out.println("myBean1.equals(myBean2) = " + myBean1.equals(myBean2));
}
}
复制代码
myBean1 = 经过FactoryBean.getObject()初始化实例
myBean2 = 经过构造方法初始化实例
myBean1.equals(myBean2) = false
复制代码
FactoryBean在Spring中最为典型的一个应用就是用来建立AOP的代理对象。源码分析
首先mybatis实现MapperScannerConfigurer,用于扫描mapper文件post
查看BeanDefinitionRegistryPostProcessor源码,发现继承于BeanFactoryPostProcessor测试
public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException;
}
复制代码
BeanFactoryPostProcessor是用于在bean被初始化为BeanDefinition
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
if (this.processPropertyPlaceHolders) {
processPropertyPlaceHolders();
}
ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
scanner.setAddToConfig(this.addToConfig);
scanner.setAnnotationClass(this.annotationClass);
scanner.setMarkerInterface(this.markerInterface);
scanner.setSqlSessionFactory(this.sqlSessionFactory);
scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
scanner.setResourceLoader(this.applicationContext);
scanner.setBeanNameGenerator(this.nameGenerator);
//用于配置扫描mapper的过滤器 我这里的filter是null的 因此直接素有mapper会加载到beanDefinition中
scanner.registerFilters();
scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
}
复制代码
scan
方法会走到doScan
public Set<BeanDefinitionHolder> doScan(String... basePackages) {
//调用父类(Spring提供的ClassPathBeanDefinitionScanner进行扫描包,扫描包的类信息、注解到 BeanDefinition,最后在通过前面定义的filter,返回一个BeanDefinitionHolder),最后调用this.registerBeanDefinition(definitionHolder, this.registry)
Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages);
if (beanDefinitions.isEmpty()) {
logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
} else {
for (BeanDefinitionHolder holder : beanDefinitions) {
GenericBeanDefinition definition = (GenericBeanDefinition) holder.getBeanDefinition();
if (logger.isDebugEnabled()) {
logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName()
+ "' and '" + definition.getBeanClassName() + "' mapperInterface");
}
// mapperInterface设为BeanName
// MapperFactoryBean设为BeanClass 后面会用到FactoryBean特性
definition.getPropertyValues().add("mapperInterface", definition.getBeanClassName());
definition.setBeanClass(MapperFactoryBean.class);
definition.getPropertyValues().add("addToConfig", this.addToConfig);
boolean explicitFactoryUsed = false;
if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionFactory != null) {
definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
explicitFactoryUsed = true;
}
if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
if (explicitFactoryUsed) {
logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
explicitFactoryUsed = true;
} else if (this.sqlSessionTemplate != null) {
if (explicitFactoryUsed) {
logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
}
definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
explicitFactoryUsed = true;
}
if (!explicitFactoryUsed) {
if (logger.isDebugEnabled()) {
logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
}
definition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
}
}
}
return beanDefinitions;
}
复制代码
这里咱们重点关注设置beanClass
设置BeanDefinition对象的BeanClass为MapperFactoryBean<?>。这意味着什么呢?以UserMapper为例,意味着当前的mapper接口在Spring容器中,beanName是userMapper,beanClass是MapperFactoryBean.class。那么在IOC初始化的时候,实例化的对象就是MapperFactoryBean对象。
如今咱们全部的**Mapper
的BeanClass
为MapperFactoryBean<?>
,由上边咱们知道,全部的FactoryBean在实例化时,会调用自身的getObject()方法,咱们查看下MapperFactoryBean<?>
这个类
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
private Class<T> mapperInterface;
private boolean addToConfig = true;
public void setMapperInterface(Class<T> mapperInterface) {
this.mapperInterface = mapperInterface;
}
public void setAddToConfig(boolean addToConfig) {
this.addToConfig = addToConfig;
}
public T getObject() throws Exception {
return getSqlSession().getMapper(this.mapperInterface);
}
public Class<T> getObjectType() {
return this.mapperInterface;
}
public boolean isSingleton() {
return true;
}
}
复制代码
调用getObject会进入getMapper
利用jdk代理反射获取对象