首先给出Spring-mybatis的配置文件
public class MapperScannerConfigurer implements BeanDefinitionRegistryPostProcessor, InitializingBean, ApplicationContextAware, BeanNameAware
这个类实现了BeanDefinitionRegistryPostProcessor这个抽象接口,让Spring容器在加载时执行postProcessBeanDefinitionRegistry方法
1 public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
2 if (this.processPropertyPlaceHolders) {
3 processPropertyPlaceHolders();
4 }
5
6 ClassPathMapperScanner scanner = new ClassPathMapperScanner(registry);
7 scanner.setAddToConfig(this.addToConfig);
8 scanner.setAnnotationClass(this.annotationClass);
9 scanner.setMarkerInterface(this.markerInterface);
10 scanner.setSqlSessionFactory(this.sqlSessionFactory);
11 scanner.setSqlSessionTemplate(this.sqlSessionTemplate);
12 scanner.setSqlSessionFactoryBeanName(this.sqlSessionFactoryBeanName);
13 scanner.setSqlSessionTemplateBeanName(this.sqlSessionTemplateBeanName);
14 scanner.setResourceLoader(this.applicationContext);
15 scanner.setBeanNameGenerator(this.nameGenerator);
16 scanner.registerFilters();
17 scanner.scan(StringUtils.tokenizeToStringArray(this.basePackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS));
18 }
可以看到 scanner设置了大量属性,并且最后执行了scan方法
public int scan(String[] basePackages)
/* */ {
/* 224 */ int beanCountAtScanStart = this.registry.getBeanDefinitionCount();
/* */
/* 226 */ doScan(basePackages);
/* */
/* */
/* 229 */ if (this.includeAnnotationConfig) {
/* 230 */ AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
/* */ }
/* */
/* 233 */ return this.registry.getBeanDefinitionCount() - beanCountAtScanStart;
/* */ }
public Set doScan(String[] basePackages)
/* */ {
/* 164 */ Set beanDefinitions = super.doScan(basePackages);
/* */
/* 166 */ if (beanDefinitions.isEmpty()) {
/* 167 */ this.logger.warn("No MyBatis mapper was found in '" + Arrays.toString(basePackages) + "' package. Please check your configuration.");
/* */ } else {
/* 169 */ processBeanDefinitions(beanDefinitions);
/* */ }
/* */
/* 172 */ return beanDefinitions;
/* */ }
Set beanDefinitions = super.doScan(basePackages);
父类的doScan
protected Set doScan(String... basePackages)
/* */ {
/* 245 */ Assert.notEmpty(basePackages, "At least one base package must be specified");
/* 246 */ Set beanDefinitions = new LinkedHashSet();
/* 247 */ for (String basePackage : basePackages) {
/* 248 */ Set candidates = findCandidateComponents(basePackage);
/* 249 */ for (BeanDefinition candidate : candidates) {
/* 250 */ ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
/* 251 */ candidate.setScope(scopeMetadata.getScopeName());
/* 252 */ String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
/* 253 */ if ((candidate instanceof AbstractBeanDefinition)) {
/* 254 */ postProcessBeanDefinition((AbstractBeanDefinition)candidate, beanName);
/* */ }
/* 256 */ if ((candidate instanceof AnnotatedBeanDefinition)) {
/* 257 */ AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition)candidate);
/* */ }
/* 259 */ if (checkCandidate(beanName, candidate)) {
/* 260 */ BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
/* 261 */ definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
/* 262 */ beanDefinitions.add(definitionHolder);
/* 263 */ registerBeanDefinition(definitionHolder, this.registry);
/* */ }
/* */ }
/* */ }
/* 267 */ return beanDefinitions;
/* */ }
然后是processBeanDefinitions
private void processBeanDefinitions(Set beanDefinitions)
/* */ {
/* 177 */ for (BeanDefinitionHolder holder : beanDefinitions) {
/* 178 */ GenericBeanDefinition definition = (GenericBeanDefinition)holder.getBeanDefinition();
/* */
/* 180 */ if (this.logger.isDebugEnabled()) {
/* 181 */ this.logger.debug("Creating MapperFactoryBean with name '" + holder.getBeanName() + "' and '" + definition
/* 182 */ .getBeanClassName() + "' mapperInterface");
/* */ }
/* */
/* */
/* */
/* 187 */ definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
/* 188 */ definition.setBeanClass(this.mapperFactoryBean.getClass());
/* */
/* 190 */ definition.getPropertyValues().add("addToConfig", Boolean.valueOf(this.addToConfig));
/* */
/* 192 */ boolean explicitFactoryUsed = false;
/* 193 */ if (StringUtils.hasText(this.sqlSessionFactoryBeanName)) {
/* 194 */ definition.getPropertyValues().add("sqlSessionFactory", new RuntimeBeanReference(this.sqlSessionFactoryBeanName));
/* 195 */ explicitFactoryUsed = true;
/* 196 */ } else if (this.sqlSessionFactory != null) {
/* 197 */ definition.getPropertyValues().add("sqlSessionFactory", this.sqlSessionFactory);
/* 198 */ explicitFactoryUsed = true;
/* */ }
/* */
/* 201 */ if (StringUtils.hasText(this.sqlSessionTemplateBeanName)) {
/* 202 */ if (explicitFactoryUsed) {
/* 203 */ this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
/* */ }
/* 205 */ definition.getPropertyValues().add("sqlSessionTemplate", new RuntimeBeanReference(this.sqlSessionTemplateBeanName));
/* 206 */ explicitFactoryUsed = true;
/* 207 */ } else if (this.sqlSessionTemplate != null) {
/* 208 */ if (explicitFactoryUsed) {
/* 209 */ this.logger.warn("Cannot use both: sqlSessionTemplate and sqlSessionFactory together. sqlSessionFactory is ignored.");
/* */ }
/* 211 */ definition.getPropertyValues().add("sqlSessionTemplate", this.sqlSessionTemplate);
/* 212 */ explicitFactoryUsed = true;
/* */ }
/* */
/* 215 */ if (!explicitFactoryUsed) {
/* 216 */ if (this.logger.isDebugEnabled()) {
/* 217 */ this.logger.debug("Enabling autowire by type for MapperFactoryBean with name '" + holder.getBeanName() + "'.");
/* */ }
/* 219 */ definition.setAutowireMode(2);
/* */ }
/* */ }
/* */ }
最关键的两行
definition.getConstructorArgumentValues().addGenericArgumentValue(definition.getBeanClassName());
definition.setBeanClass(this.mapperFactoryBean.getClass());
所以最终我们还是要分析MapperFactoryBean的实现原理!
MapperFactoryBean继承了SqlSessionDaoSupport类,SqlSessionDaoSupport类继承DaoSupport抽象类,DaoSupport抽象类实现了InitializingBean接口,因此实例个MapperFactoryBean的时候,都会调用InitializingBean接口的afterPropertiesSet方法。
public final void afterPropertiesSet() throws IllegalArgumentException, BeanInitializationException
/* */ {
/* 44 */ checkDaoConfig();
/* */
/* */ try
/* */ {
/* 48 */ initDao();
/* */ }
/* */ catch (Exception ex) {
/* 51 */ throw new BeanInitializationException("Initialization of DAO failed", ex);
/* */ }
/* */ }
protected void checkDaoConfig()
/* */ {
/* 74 */ super.checkDaoConfig();
/* */
/* 76 */ Assert.notNull(this.mapperInterface, "Property 'mapperInterface' is required");
/* */
/* 78 */ Configuration configuration = getSqlSession().getConfiguration();
/* 79 */ if ((this.addToConfig) && (!configuration.hasMapper(this.mapperInterface))) {
/* */ try {
/* 81 */ configuration.addMapper(this.mapperInterface);
/* */ } catch (Exception e) {
/* 83 */ this.logger.error("Error while adding the mapper '" + this.mapperInterface + "' to configuration.", e);
/* 84 */ throw new IllegalArgumentException(e);
/* */ } finally {
/* 86 */ ErrorContext.instance().reset();
/* */ }
/* */ }
/* */ }
public T getObject()
/* */ throws Exception
/* */ {
/* 96 */ return getSqlSession().getMapper(this.mapperInterface);
/* */ }
public T getMapper(Class type)
/* */ {
/* 319 */ return getConfiguration().getMapper(type, this);
/* */ }
public T getMapper(Class type, SqlSession sqlSession) {
/* 717 */ return this.mapperRegistry.getMapper(type, sqlSession);
/* */ }
getMapper
*/ public T getMapper(Class type, SqlSession sqlSession)
/* */ {
/* 45 */ MapperProxyFactory mapperProxyFactory = (MapperProxyFactory)this.knownMappers.get(type);
/* 46 */ if (mapperProxyFactory == null) {
/* 47 */ throw new BindingException("Type " + type + " is not known to the MapperRegistry.");
/* */ }
/* */ try {
/* 50 */ return mapperProxyFactory.newInstance(sqlSession);
/* */ } catch (Exception e) {
/* 52 */ throw new BindingException("Error getting mapper instance. Cause: " + e, e);
/* */ }
/* */ }
protected T newInstance(MapperProxy mapperProxy)
/* */ {
/* 47 */ return Proxy.newProxyInstance(this.mapperInterface.getClassLoader(), new Class[] { this.mapperInterface }, mapperProxy);
/* */ }
/* */
mapperProxy的源码
public class MapperProxy
/* */ implements InvocationHandler, Serializable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
/* */ {
/* 45 */ if (Object.class.equals(method.getDeclaringClass())) {
/* */ try {
/* 47 */ return method.invoke(this, args);
/* */ } catch (Throwable t) {
/* 49 */ throw ExceptionUtil.unwrapThrowable(t);
/* */ }
/* */ }
/* 52 */ MapperMethod mapperMethod = cachedMapperMethod(method);
/* 53 */ return mapperMethod.execute(this.sqlSession, args);
/* */ }
MapperMethod mapperMethod = cachedMapperMethod(method);
/* 53 */ return mapperMethod.execute(this.sqlSession, args);