SSM框架(1):使用Maven搭建SSM项目实践

一、推荐阅读

  1. MyBatis(1)——快速入门
  2. MyBatis(2)——MyBatis 深入学习
  3. Maven整合SSM框架

 

二、实践中的问题 - Spring\SpringMVC

问题一:@Service 和 @Resource注解的误用 

两个注解的作用:
@Service("XXX"):用在类上。相当于将这个类定义为一个bean,bean的名称为XXX; @Resource(name="xxx"):用在类的引用型属性上。当需要在某个类中定义一个属性,并且该属性是一个已在的bean,要为该属性赋值或注入时在该属性上一行使用@Resource(name="XXX")注解,相当于为该属性注入一个名称为xxx的bean。
  • 知识扩展:

  Spring不但支持自己定义的@Autowired注解,还支持几个由JSR-250规范定义的注解,它们分别是@Resource、@PostConstruct以及@PreDestroy。 

  @Resource的作用相当于@Autowired,只不过@Autowired按byType自动注入,而@Resource默认按 byName自动注入罢了。@Resource有两个属性是比较重要的,分是name和type,Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。所以如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果既不指定name也不指定type属性,这时将通过反射机制使用byName自动注入策略。

  @Resource装配顺序

  1. 如果同时指定了name和type,则从Spring上下文中找到唯一匹配的bean进行装配,找不到则抛出异常
  2. 如果指定了name,则从上下文中查找名称(id)匹配的bean进行装配,找不到则抛出异常
  3. 如果指定了type,则从上下文中找到类型匹配的唯一bean进行装配,找不到或者找到多个,都会抛出异常
  4. 如果既没有指定name,又没有指定type,则自动按照byName方式进行装配;如果没有匹配,则回退为一个原始类型进行匹配,如果匹配则自动装配

 

三、实践中的问题 - MyBatis

问题一:MyBatis动态代理实例化DAO接口时报错,提示无法实例化扫描类 MapperScannerConigurer

报错信息如下:
 Error creating bean with name 'org.mybatis.spring.mapper.MapperScannerConfigurer#0'
//解决办法:在配置bena:MapperScannerConigurer时,使用参数sqlSessionFactoryBeanName来设置工厂类实例
<!-- 配置扫描DAO 接口包,动态实现DAO接口实例,注入到Spring容器中进行管理 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!-- 注入SqlSession工厂对象:SqlSessionFactoryBean -->
<!--<property name="sqlSessionFactory" ref="sqlSessionFactory"/>-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!-- 指定要扫描的DAO接口所在包 -->
<property name="basePackage" value="com.newbie.dao"/>
</bean>
<!-- 配置工厂对象: SqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
<!--扫描com.newbie.domain包,使用类的别名(默认首字母小写) -->
<property name="typeAliasesPackage" value="com.newbie.domain"/>
<!-- 扫描sqlMapper配置文件:userMapper.xml-->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
</bean>
原因分析:
  MapperScannerConigurer实际是在解析加载bean定义阶段实例化的,这个时候要是设置sqlSessionFactory的话,会导致提前初始化一些类,但是,此时PropertyPlaceholderConfigurer还没来得及替换定义中的变量数据,导致把表达式当作字符串复制了。

解决办法:
第一种方式:在配置bena:MapperScannerConigurer时,使用参数sqlSessionFactoryBeanName来设置工厂类实例.原理:使用sqlSessionFactoryBeanName注入,不会立即初始化sqlSessionFactory, 所以不会引发提前初始化问题。
    即:
  修改 property name="sqlSessionFactory" ref="sqlSessionFactory" 
  改为 property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"

第二种:直接删掉。原理:在配置bena:MapperScannerConigurer时,不配置sqlSessionFactory,由容器自动注入依赖。

 

问题二:动态实例接口IUserDAO时,接口中的selectAll()方法没有实现

报错信息:
org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.newbie.dao.IUserDAO.selectAll
原因分析:
检查UserMapper.xml文件中的mapper配置信息,发现namespace="***"属性值不是IUserDAO的全类名。

解决办法:
修改namespace属性值,改为namespace="com.newbie.dao.IUserDAO"
<!-- mapper配置文件,其中namespace指定要动态实例的DAO接口全局类名称 -->
<mapper namespace="com.newbie.dao.IUserDAO">
  • 知识扩展:Invalid bound statement (not found)错误的原因是:接口IUserDAO 和 配置文件UserMapper.xml之间匹配有问题。

  排查步骤:

    (1)检查配置的UserMapper.xml的路径是否正确;

    (2)检查UserMapper.xml 所在的package名称 和 接口IUserDAO 所在的包名称是否相同;

    (3)接口IUserDAO中的方法,在配置文件UserMapper.xml 中是否存在;

    (4)接口IUserDAO中的方法返回值是Lis<User>,而UserMapper.xml中对应的select节点是否配置有ResultMap;

 

 

 

 

 

   

posted @ 2019-05-06 22:36  荆小六  阅读(424)  评论(0编辑  收藏  举报