由mybatis-spring總結Spring的一般註解問題,xml的方式,bean的註冊和使用

 

  • 一種是@Autowired 、@Resource 、@PostConstruct、@PreDestroy、@PersistenceContext、@Required系列註解

       最原始的使用其他類的方式是 A a=new A();
       這種註解是用來用其他的bean的,代替自動注入(兩種方式,一種getBean(),另一種是把自己也配置成bean,property是要使用的那個bean,然後自己的類中就能使用自己的屬性了(要使用的那個bean))。
      但是要配合<context:annotation- config/>或者<context:component-scan>(完全可以代替<context:annotation- config/>)使用,因爲他們是使上述註解起作用的,也就是說激活已經在application context中註冊的bean

  • 另一種是@Component,@Repository,@Service, @Controller @RestController, @ControllerAdvice,  @Configuration系列註解

      這系列註解是聲明要將它註解的類註冊成bean
      但是要配合<context:component-scan/>標籤使用,<context:component-scan>做了<context:annotation-config>要做的事情,還額外支持@Component,@Repository,@Service, @Controller @RestController, @ControllerAdvice, and @Configuration 註解,並且<context:component-scan>掃描base-package並且在application context中註冊掃描到的使用註解注入的beans。
這裏着重注意第二段話,<context:component-scan>該註解可以掃描並註冊你使用註解諸如@controller @service @component..的bean!!!也就是說,你不用xml中顯示配置,需要的時候儘管用@Resource或者@Autowired來自動注入!!!
     總結一下就是:component-scan標籤默認情況下自動掃描指定路徑下的包(含所有子包),將帶有 @Component @Repository @Service @Controller標籤的類自動註冊到spring容器。(@Component等註解是註冊bean用的,由<component-scan>將他們掃描並註冊。)對標記了 Spring中的 @Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB   @PersistenceContext @PersistenceUnit等註解的類進行對應的操作使註解生效(包含了annotation-config標籤的作用)。(@Autowired等註解是自動注入bean用的,<annotation-config>和<component-scan>是使這些註解起作用的。)


      基於內容,可以知道註冊bean、使用bean的方式。

      最原始的使用其他類的方式是 A a=new A()。

      當有了Spring後,我們可以使用IoC注入。

     最基礎的註冊bean的方式是Spring的配置xml中註冊bean,但是有了@Component系列註解加上<context:component-scan/>標籤後我們就不用再在Spring的配置xml中一個個註冊了

     使用bean的方式,Spring基礎的是一種getBean(),另一種是把自己也配置成bean,property是要使用的那個bean,然後自己的類中就能使用自己的屬性了(要使用的那個bean);但是有了@Autowired後,只要你註冊了bean(@Autowired註解在你使用的時候自動注入的前提是,spring容器中已經有了該bean),你就可以在要使用其他bean的地方(例如Service層)直接使用那個bean。

     @Autowired/@Resource  和  @Component既可以結合使用,單獨使用也是可以的。

     但是使用mybatis-spring時,有個問題發生了,那就是不能用@Repository +<context:component-scan/>註冊mapper層,必須得用MapperFactoryBean或MapperScannerConfigurer動態代理註冊mapper的bean。


      下面結合mybatis-spring的一個簡單例子談註解問題

<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
  <property name="mapperInterface" value="org.mybatis.spring.sample.mapper.UserMapper" />
  <property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<bean id="fooService" class="org.mybatis.spring.sample.mapper.FooServiceImpl">
  <property name="userMapper" ref="userMapper" />
</bean>

public interface UserMapper {
  @Select("SELECT * FROM users WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
} 

public class FooServiceImpl implements FooService {

  private UserMapper userMapper;

  public void setUserMapper(UserMapper userMapper) {
    this.userMapper = userMapper;
  }

  public User doSomeBusinessStuff(String userId) {
    return this.userMapper.getUser(userId);
  }
}

    1.之前只有Mybatis時,用mapper.java和mapper.xml的使用方式是在該用的地方通過getMapper()的方式:BlogMapper mapper = session.getMapper(BlogMapper.class);   Blog blog = mapper.selectBlog(101);

     2.我以爲我們可以通過給mapper接口註冊bean<bean class="com.  .Mapper.BlogMapper",然後在要使用mapper接口的地方(比如Service層,Main.java)使用。最原始的是spring xml中<bean ...>,然後要使用mapper接口的地方mapper =factory.getBean();mapper.selectBlog(101);或者把Service也配置成一個bean,property是mapper的bean,這樣Service就可以使用自己的屬性了(這是我想的Spring的IoC注入方式,不過這種方式一般是用於類的,mapper接口應該不能直接這麼用)。

    3.事實是mybatis的mapper層是接口,不能直接這麼用,應該spring-common.xml中使用代理類MapperFactoryBean配置bean,如上面代碼一樣。然後在 business/service 對象中以和注入任意 Spring bean 的相同方式直接注入映射器,這樣Service裏面沒法直接也可以使用mapper.java了(這是Spring IoC注入的另一種形式:把自己配成bean直接用屬性;)或者在Service層使用@Autowired+<context:component-scan/>;至於能不能getBean("userMapper")我沒試過,不知道。

     4.MapperFactoryBean升級版的是使用MapperScannerConfigurer,因爲沒有必要在 Spring 的 XML 配置文件中註冊所有的映射器,相反,你可以使用一個 MapperScannerConfigurer , 它 將 會 查 找 類 路 徑 下 的 映 射 器 並 自 動 將 它 們 創 建 成 MapperFactoryBean。在這種情況下,是沒法使用Service配置成含屬性mapper的bean的方法了,應該Service層通過@Autowired使用mapper。

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
  <property name="basePackage" value="cn.neusoft.mapper" />
</bean>

      5.因爲MapperScannerConfigurer也是用來註冊bean的,而@Repository +<context:component-scan/>就可以將dao層自動註冊成bean,無需在xml中配置,所以我在想,能不能spring-common.xml中不寫MapperScannerConfigurer,將Mapper接口用@Repository +<context:component-scan/>註解。經過用項目實驗,證明是錯誤的,會報錯沒有註冊mapper的bean。這讓我非常疑惑,@Repository +<context:component-scan/>明明就可以註冊dao層的bean,查看一些資料

MyBatis-Spring 提供了一個動態代理的實現:MapperFactoryBean。這個類 可以讓你直接注入數據映射器接口到你的 service 層 bean 中。當使用映射器時,你僅僅如調 用你的 DAO 一樣調用它們就可以了,但是你不需要編寫任何 DAO 實現的代碼,因爲 MyBatis-Spring 將會爲你創建代理。

      所以我猜測是不是因爲mybatis的mapper層是接口,是通過代理類實現註冊bean的,所以不能通過@Repository +<context:component-scan/>註冊,而正常的dao層是可以@Repository +<context:component-scan/>簡便註冊bean的。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章