1. 程式人生 > 其它 >Spring一套全通6—註解程式設計

Spring一套全通6—註解程式設計

百知教育 --- Spring系列課程 --- 註解程式設計


第一章、註解基礎概念

1. 什麼是註解程式設計
指的是在類或者方法上加入特定的註解(@XXX),完成特定功能的開發。
  
	@Component
public class XXX{}
2. 為什麼要講解註解程式設計
1. 註解開發方便
     程式碼簡潔 開發速度大大提高
2. Spring開發潮流
     Spring2.x引入註解  Spring3.x完善註解 SpringBoot普及 推廣註解程式設計 
3. 註解的作用
  • 替換XML這種配置形式,簡化配置

  • 替換介面,實現呼叫雙方的契約性

    通過註解的方式,在功能呼叫者和功能提供者之間達成約定,進而進行功能的呼叫。因為註解應用更為方便靈活,所以在現在的開發中,更推薦通過註解的形式,完成
    
4. Spring註解的發展歷程
1. Spring2.x開始支援註解程式設計 @Component @Service @Scope..
     目的:提供的這些註解只是為了在某些情況下簡化XML的配置,作為XML開發的有益補充。
2. Spring3.x @Configuration @Bean..
     目的:徹底替換XML,基於純註解程式設計
3. Spring4.x SpringBoot 
     提倡使用註解常見開發
5. Spring註解開發的一個問題
Spring基於註解進行配置後,還能否解耦合呢?

在Spring框架應用註解時,如果對註解配置的內容不滿意,可以通過Spring配置檔案進行覆蓋的。

第二章、Spring的基礎註解(Spring2.x)

這個階段的註解,僅僅是簡化XML的配置,並不能完全替代XML
1. 物件建立相關注解
  • 搭建開發環境

    <context:component-scan base-package="com.baizhiedu"/>
    
    作用:讓Spring框架在設定包及其子包中掃描對應的註解,使其生效。
    
  • 物件建立相關注解

    • @Component

      作用:替換原有spring配置檔案中的<bean標籤 
      注意:
          id屬性 component註解 提供了預設的設定方式  首單詞首字母小寫
          class屬性 通過反射獲得class內容 
      
    • @Component 細節

      • 如何顯示指定工廠建立物件的id值

        @Component("u")
        
      • Spring配置檔案覆蓋註解配置內容

        applicationContext.xml
        
        <bean id="u" class="com.baizhiedu.bean.User"/>
        
        id值 class的值 要和 註解中的設定保持一值 
        
    • @Component的衍生註解

      @Repository  --->  XXXDAO
        @Repository
        public class UserDAO{
        
        }
      @Service
        @Service
        public class UserService{
        
        }
      @Controller 
        @Controller 
        public class RegAction{
        
        }
      注意:本質上這些衍生註解就是@Component 
           作用 <bean  
           細節 @Service("s")
      
      目的:更加準確的表達一個型別的作用
      
      注意:Spring整合Mybatis開發過程中 不使用@Repository @Component
           
      
  • @Scope註解

    作用:控制簡單物件建立次數
    注意:不新增@Scope Spring提供預設值 singleton
    <bean id="" class="" scope="singleton|prototype"/>
    
  • @Lazy註解

    作用:延遲建立單例項物件
    注意:一旦使用了@Lazy註解後,Spring會在使用這個物件時候,進行這個物件的建立
    <bean id="" class="" lazy="false"/>
    
  • 生命週期方法相關注解

    1. 初始化相關方法 @PostConstruct
       InitializingBean
       <bean init-method=""/>
    2. 銷燬方法 @PreDestroy
       DisposableBean
       <bean destory-method=""/>
    注意:1. 上述的2個註解並不是Spring提供的,JSR(JavaEE規範)520
         2. 再一次的驗證,通過註解實現了介面的契約性
    
2. 注入相關注解
  • 使用者自定義型別 @Autowired

    @Autowired細節
    1. Autowired註解基於型別進行注入 [推薦]
       基於型別的注入:注入物件的型別,必須與目標成員變數型別相同或者是其子類(實現類)
    
    2. Autowired Qualifier 基於名字進行注入 [瞭解]
       基於名字的注入:注入物件的id值,必須與Qualifier註解中設定的名字相同
    
    3. Autowired註解放置位置 
        a) 放置在對應成員變數的set方法上 
        b) 直接把這個註解放置在成員變數之上,Spring通過反射直接對成員變數進行注入(賦值)[推薦]
    
    4. JavaEE規範中類似功能的註解
        JSR250 @Resouce(name="userDAOImpl") 基於名字進行注入
               @Autowired()
               @Qualifier("userDAOImpl")
               注意:如果在應用Resource註解時,名字沒有配對成功,那麼他會繼續按照型別進行注入。
        JSR330 @Inject 作用 @Autowired完全一致 基於型別進行注入 ---》 EJB3.0
              <dependency>
                <groupId>javax.inject</groupId>
                <artifactId>javax.inject</artifactId>
                <version>1</version>
              </dependency>
    
  • JDK型別

    @Value註解完成
    1. 設定xxx.properties 
       id = 10
       name = suns
    2. Spring的工廠讀取這個配置檔案 
       <context:property-placeholder location=""/>
    3. 程式碼 
       屬性 @Value("${key}")
    
    • @PropertySource

      1. 作用:用於替換Spring配置檔案中的<context:property-placeholder location=""/>標籤
      2. 開發步驟 
          1. 設定xxx.properties 
             id = 10
             name = suns
          2. 應用@PropertySource
          3. 程式碼
             屬性 @Value()
      
    • @Value註解使用細節

      • @Value註解不能應用在靜態成員變數上

        如果應用,賦值(注入)失敗
        
      • @Value註解+Properties這種方式,不能注入集合型別

        Spring提供新的配置形式 YAML YML (SpringBoot)
        
3. 註解掃描詳解
<context:component-scan base-package="com.baizhiedu"/>
當前包 及其 子包 
1. 排除方式
<context:component-scan base-package="com.baizhiedu">
   <context:exclude-filter type="" expression=""/>
   type:assignable:排除特定的型別 不進行掃描
        annotation:排除特定的註解 不進行掃描
        aspectj:切入點表示式
                包切入點: com.baizhiedu.bean..*
                類切入點: *..User
        regex:正則表示式 
        custom:自定義排除策略框架底層開發
</context:component-scan>

排除策略可以疊加使用 
<context:component-scan base-package="com.baizhiedu">
  <context:exclude-filter type="assignable" expression="com.baizhiedu.bean.User"/>

  <context:exclude-filter type="aspectj" expression="com.baizhiedu.injection..*"/>
</context:component-scan>
2. 包含方式
<context:component-scan base-package="com.baizhiedu" use-default-filters="false">
   <context:include-filter type="" expression=""/>
</context:component-scan>

1. use-default-filters="false"
   作用:讓Spring預設的註解掃描方式 失效。
2. <context:include-filter type="" expression=""/>
   作用:指定掃描那些註解 
   type:assignable:排除特定的型別 不進行掃描
        annotation:排除特定的註解 不進行掃描
        aspectj:切入點表示式
                包切入點: com.baizhiedu.bean..*
                類切入點: *..User
        regex:正則表示式 
        custom:自定義排除策略框架底層開發

包含的方式支援疊加
 <context:component-scan base-package="com.baizhiedu" use-default-filters="false">
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Repository"/>
        <context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
 </context:component-scan>
4. 對於註解開發的思考
  • 配置互通

    Spring註解配置 配置檔案的配置 互通
    
    @Repository
    public class UserDAOImpl{
    
    
    }
    
    public class UserServiceImpl{
       private UserDAO userDAO;
       set get
    }
    
    <bean id="userService" class="com.baizhiedu.UserServiceImpl">
       <property name="userDAO" ref="userDAOImpl"/>
    </bean>
    
  • 什麼情況下使用註解 什麼情況下使用配置檔案

    @Component 替換 <bean 
    
    基礎註解(@Component @Autowired @Value) 程式設計師開發型別的配置
    
    1. 在程式設計師開發的型別上 可以加入對應註解 進行物件的建立 
       User  UserService  UserDAO  UserAction 
    
    2. 應用其他非程式設計師開發的型別時,還是需要使用<bean 進行配置的
       SqlSessionFactoryBean  MapperScannerConfigure 
    
5. SSM整合開發(半註解開發)
  • 搭建開發環境

    • 引入相關jar 【SSM POM】
    • 引入相關配置檔案
      • applicationContext.xml
      • struts.xml
      • log4.properties
      • XXXMapper.xml
    • 初始化配置
      • Web.xml Spring (ContextLoaderListener)
      • Web.xml Struts Filter
  • 編碼

    <context:component-scan base-package=""/>
    
    • DAO (Spring+Mybatis)

      1. 配置檔案的配置
         1. DataSource
         2. SqlSessionFactory ----> SqlSessionFactoryBean
            1. dataSource
            2. typeAliasesPackage
            3. mapperLocations 
         3. MapperScannerConfigur ---> DAO介面實現類
      2. 編碼
         1. entity 
         2. table
         3. DAO介面
         4. 實現Mapper檔案
      
    • Service

      1. 原始物件 ---》 注入DAO
         @Service ---> @Autowired
      
      2. 額外功能 ---》 DataSourceTransactionManager ---> dataSource
      3. 切入點 + 事務屬性
         @Transactional(propagation,readOnly...)
      4. 組裝切面
         <tx:annotation-driven 
      
    • Controller (Spring+Struts2)

      1. @Controller
         @Scope("prototype")
         public class RegAction implements Action{
            @Autowired
            private UserService userServiceImpl;
         
         }
      2. struts.xml
          <action class="spring配置檔案中action對應的id值"/>
      

第三章、Spring的高階註解(Spring3.x 及以上)

1. 配置Bean
Spring在3.x提供的新的註解,用於替換XML配置檔案。
  
  @Configuration
public class AppConfig{
  
}
  1. 配置Bean在應用的過程中 替換了XML具體什麼內容呢?

  2. AnnotationConfigApplicationContext

    1. 建立工廠程式碼
       ApplicationContext ctx = new AnnotationConfigApplicationContext();
    2. 指定配置檔案 
       1. 指定配置bean的Class
           ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
       2. 指定配置bean所在的路徑 
           ApplicationContext ctx = new AnnotationConfigApplicationContext("com.baizhiedu");
    
  • 配置Bean開發的細節分析

    • 基於註解開發使用日誌

      不能整合Log4j
      整合logback 
      
      • 引入相關jar

         <dependency>
              <groupId>org.slf4j</groupId>
              <artifactId>slf4j-api</artifactId>
              <version>1.7.25</version>
            </dependency>
        
            <dependency>
              <groupId>org.slf4j</groupId>
              <artifactId>jcl-over-slf4j</artifactId>
              <version>1.7.25</version>
            </dependency>
        
            <dependency>
              <groupId>ch.qos.logback</groupId>
              <artifactId>logback-classic</artifactId>
              <version>1.2.3</version>
            </dependency>
        
            <dependency>
              <groupId>ch.qos.logback</groupId>
              <artifactId>logback-core</artifactId>
              <version>1.2.3</version>
            </dependency>
        
            <dependency>
              <groupId>org.logback-extensions</groupId>
              <artifactId>logback-ext-spring</artifactId>
              <version>0.1.4</version>
            </dependency>
        
      • 引入logback配置檔案 (logback.xml)

        <?xml version="1.0" encoding="UTF-8"?>
        <configuration>
            <!-- 控制檯輸出 -->
            <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
                <encoder>
                    <!--格式化輸出:%d表示日期,%thread表示執行緒名,%-5level:級別從左顯示5個字元寬度%msg:日誌訊息,%n是換行符-->
                    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
                </encoder>
            </appender>
        
            <root level="DEBUG">
                <appender-ref ref="STDOUT" />
            </root>
        
        </configuration>
        
    • @Configuration註解的本質

      本質:也是@Component註解的衍生註解
      
      可以應用<context:component-scan進行掃描
      
2. @Bean註解
@Bean註解在配置bean中進行使用,等同於XML配置檔案中的<bean標籤
1. @Bean註解的基本使用
  • 物件的建立

    1. 簡單物件
       直接能夠通過new方式建立的物件 
       User  UserService   UserDAO 
    2. 複雜物件
       不能通過new的方式直接建立的物件
       Connection SqlSessionFactory
    
    • @Bean註解建立複雜物件的注意事項

      遺留系統整合 
      @Bean
      public Connection conn1() {
        Connection conn = null;
        try {
          ConnectionFactoryBean factoryBean = new ConnectionFactoryBean();
          conn = factoryBean.getObject();
        } catch (Exception e) {
          e.printStackTrace();
        }
        return conn;
      }
      
  • 自定義id值

    @Bean("id")
    
  • 控制物件建立次數

    @Bean
    @Scope("singleton|prototype") 預設值 singleton
    
2. @Bean註解的注入
  • 使用者自定義型別

    @Bean
    public UserDAO userDAO() {
      return new UserDAOImpl();
    }
    
    @Bean
    public UserService userService(UserDAO userDAO) {
      UserServiceImpl userService = new UserServiceImpl();
      userService.setUserDAO(userDAO);
      return userService;
    }
    
    //簡化寫法
    @Bean
    public UserService userService() {
      UserServiceImpl userService = new UserServiceImpl();
      userService.setUserDAO(userDAO());
      return userService;
    }
    
  • JDK型別的注入

    @Bean
    public Customer customer() {
      Customer customer = new Customer();
      customer.setId(1);
      customer.setName("xiaohei");
    
      return customer;
    }
    
    • JDK型別注入的細節分析

      如果直接在程式碼中進行set方法的呼叫,會存在耦合的問題 
      
      @Configuration
      @PropertySource("classpath:/init.properties")
      public class AppConfig1 {
      
          @Value("${id}")
          private Integer id;
          @Value("${name}")
          private String name;
       
          @Bean
          public Customer customer() {
              Customer customer = new Customer();
              customer.setId(id);
              customer.setName(name);
      
              return customer;
          }
      }
      
3. @ComponentScan註解
@ComponentScan註解在配置bean中進行使用,等同於XML配置檔案中的<context:component-scan>標籤

目的:進行相關注解的掃描 (@Component @Value ...@Autowired)
1. 基本使用
@Configuration
@ComponentScan(basePackages = "com.baizhiedu.scan")
public class AppConfig2 {

}

<context:component-scan base-package=""/>
2. 排除、包含的使用
  • 排除

    <context:component-scan base-package="com.baizhiedu">
      <context:exclude-filter type="assignable" expression="com.baizhiedu.bean.User"/>
    </context:component-scan>
    
    @ComponentScan(basePackages = "com.baizhiedu.scan",
                   excludeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class}),
                                     @ComponentScan.Filter(type= FilterType.ASPECTJ,pattern = "*..User1")})
    
    type = FilterType.ANNOTATION          value
                     .ASSIGNABLE_TYPE     value
                     .ASPECTJ             pattern   
                     .REGEX               pattern
                     .CUSTOM              value
    
  • 包含

    <context:component-scan base-package="com.baizhiedu" use-default-filters="false">
       <context:include-filter type="" expression=""/>
    </context:component-scan>
    
    @ComponentScan(basePackages = "com.baizhiedu.scan",
                   useDefaultFilters = false,
                   includeFilters = {@ComponentScan.Filter(type= FilterType.ANNOTATION,value={Service.class})})
    
    type = FilterType.ANNOTATION          value
                     .ASSIGNABLE_TYPE     value
                     .ASPECTJ             pattern   
                     .REGEX               pattern
                     .CUSTOM              value
    
4. Spring工廠建立物件的多種配置方式
1. 多種配置方式的應用場景
2. 配置優先順序
@Component及其衍生註解 < @Bean < 配置檔案bean標籤
優先順序高的配置 覆蓋優先順序低配置 

@Component
public class User{

}

@Bean
public User user(){
  return new User();
}

<bean id="user" class="xxx.User"/>

配置覆蓋:id值 保持一致
  • 解決基於註解進行配置的耦合問題

    @Configuration
    //@ImportResource("applicationContext.xml")
    public class AppConfig4 {
    
        @Bean
        public UserDAO userDAO() {
            return new UserDAOImpl();
        }
    }
    
    @Configuration
    @ImportResource("applicationContext.xml")
    public class AppConfig5{
      
    }
    
    applicationContext.xml
    <bean id="userDAO" class="com.baizhiedu.injection.UserDAOImplNew"/>
    
5. 整合多個配置資訊
  • 為什麼會有多個配置資訊
拆分多個配置bean的開發,是一種模組化開發的形式,也體現了面向物件各司其職的設計思想
  • 多配置資訊整合的方式
    • 多個配置Bean的整合
    • 配置Bean與@Component相關注解的整合
    • 配置Bean與SpringXML配置檔案的整合
  • 整合多種配置需要關注那些要點
    • 如何使多配置的資訊 彙總成一個整體
    • 如何實現跨配置的注入
1. 多個配置Bean的整合
  • 多配置的資訊彙總

    • base-package進行多個配置Bean的整合

    • @Import

      1. 可以建立物件
      2. 多配置bean的整合
      
    • 在工廠建立時,指定多個配置Bean的Class物件 【瞭解】

      ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig1.class,AppConfig2.class);
      
  • 跨配置進行注入

    在應用配置Bean的過程中,不管使用哪種方式進行配置資訊的彙總,其操作方式都是通過成員變數加入@Autowired註解完成。
    @Configuration
    @Import(AppConfig2.class)
    public class AppConfig1 {
    
        @Autowired
        private UserDAO userDAO;
    
        @Bean
        public UserService userService() {
            UserServiceImpl userService = new UserServiceImpl();
            userService.setUserDAO(userDAO);
            return userService;
        }
    }
    
    @Configuration
    public class AppConfig2 {
    
        @Bean
        public UserDAO userDAO() {
            return new UserDAOImpl();
        }
    }
    
2. 配置Bean與@Component相關注解的整合
@Component(@Repository)
public class UserDAOImpl implements UserDAO{
  
}

@Configuration
@ComponentScan("")
public class AppConfig3 {
   
    @Autowired
    private UserDAO userDAO;

    @Bean
    public UserService userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAO(userDAO);
        return userService;
    }
}

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig3.class);
3. 配置Bean與配置檔案整合
1. 遺留系統的整合 2. 配置覆蓋
  
public class UserDAOImpl implements UserDAO{
  
}
<bean id="userDAO" class="com.baizhiedu.injection.UserDAOImpl"/>

@Configuration
@ImportResource("applicationContext.xml")
public class AppConfig4 {
  
    @Autowired
    private UserDAO userDAO;

    @Bean
    public UserService userService() {
        UserServiceImpl userService = new UserServiceImpl();
        userService.setUserDAO(userDAO);
        return userService;
    }
}

ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig4.class);
6. 配置Bean底層實現原理
Spring在配置Bean中加入了@Configuration註解後,底層就會通過Cglib的代理方式,來進行物件相關的配置、處理
7. 四維一體的開發思想
1. 什麼是四維一體
Spring開發一個功能的4種形式,雖然開發方式不同,但是最終效果是一樣的。
1. 基於schema
2. 基於特定功能註解
3. 基於原始<bean
4. 基於@Bean註解
2. 四維一體的開發案例
1. <context:property-placehoder
2. @PropertySource  【推薦】
3. <bean id="" class="PropertySourcePlaceholderConfigure"/>
4. @Bean            【推薦】
8. 純註解版AOP程式設計
1. 搭建環境
1. 應用配置Bean 
2. 註解掃描
2. 開發步驟
1. 原始物件
   @Service(@Component)
   public class UserServiceImpl implements UserService{
     
   }
2. 建立切面類 (額外功能 切入點 組裝切面)
    @Aspect
    @Component
    public class MyAspect {

        @Around("execution(* login(..))")
        public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {

            System.out.println("----aspect log ------");

            Object ret = joinPoint.proceed();


            return ret;
        }
    }
3. Spring的配置檔案中
   <aop:aspectj-autoproxy />
   @EnableAspectjAutoProxy ---> 配置Bean 
3. 註解AOP細節分析
1. 代理建立方式的切換 JDK Cglib 
   <aop:aspectj-autoproxy proxy-target-class=true|false />
   @EnableAspectjAutoProxy(proxyTargetClass)
2. SpringBoot AOP的開發方式
     @EnableAspectjAutoProxy 已經設定好了 
     
    1. 原始物件
     @Service(@Component)
     public class UserServiceImpl implements UserService{

     }
    2. 建立切面類 (額外功能 切入點 組裝切面)
      @Aspect
      @Component
      public class MyAspect {

        @Around("execution(* login(..))")
        public Object arround(ProceedingJoinPoint joinPoint) throws Throwable {

          System.out.println("----aspect log ------");

          Object ret = joinPoint.proceed();


          return ret;
        }
      }
    Spring AOP 代理預設實現 JDK  SpringBOOT AOP 代理預設實現 Cglib 
9. 純註解版Spring+MyBatis整合
  • 基礎配置 (配置Bean)

    1. 連線池
      <!--連線池-->
      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/suns?useSSL=false"></property>
        <property name="username" value="root"></property>
        <property name="password" value="123456"></property>
      </bean>
       
       @Bean
       public DataSource dataSource(){
          DruidDataSource dataSource = new DruidDataSource();
          dataSource.setDriverClassName("");
          dataSource.setUrl();
          ...
          return dataSource;
       }
    
    2. SqlSessionFactoryBean
        <!--建立SqlSessionFactory SqlSessionFactoryBean-->
        <bean id="sqlSessionFactoryBean" class="org.mybatis.spring.SqlSessionFactoryBean">
          <property name="dataSource" ref="dataSource"></property>
          <property name="typeAliasesPackage" value="com.baizhiedu.entity"></property>
          <property name="mapperLocations">
            <list>
              <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
            </list>
          </property>
        </bean>
    
        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){
             SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
             sqlSessionFactoryBean.setDataSource(dataSource);
             sqlSessionFactoryBean.setTypeAliasesPackage("");
             ...
             return sqlSessionFactoryBean;
        }
    
    3. MapperScannerConfigure 
       <!--建立DAO物件 MapperScannerConfigure-->
      <bean id="scanner" class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactoryBean"></property>
        <property name="basePackage" value="com.baizhiedu.dao"></property>
      </bean>
      
      @MapperScan(basePackages={"com.baizhiedu.dao"}) ---> 配置bean完成
      
    
  • 編碼

    1. 實體
    2. 表
    3. DAO介面
    4. Mapper檔案 
    
    1. MapperLocations編碼時通配的寫法
    //設定Mapper檔案的路徑
    sqlSessionFactoryBean.setMapperLocations(Resource..);
    Resource resouce = new ClassPathResouce("UserDAOMapper.xml")
      
    sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
    
    <property name="mapperLocations">
       <list>
         <value>classpath:com.baizhiedu.mapper/*Mapper.xml</value>
       </list>
    </property>
    一組Mapper檔案 
    
    ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
    Resource[] resources = resolver.getResources("com.baizhi.mapper/*Mapper.xml");
    sqlSessionFactoryBean.setMapperLocations(resources)
    
    2. 配置Bean資料耦合的問題
    mybatis.driverClassName = com.mysql.jdbc.Driver
    mybatis.url = jdbc:mysql://localhost:3306/suns?useSSL=false
    mybatis.username = root
    mybatis.password = 123456
    mybatis.typeAliasesPackages = com.baizhiedu.mybatis
    mybatis.mapperLocations = com.baizhiedu.mapper/*Mapper.xml
    
    @Component
    @PropertySource("classpath:mybatis.properties")
    public class MybatisProperties {
        @Value("${mybatis.driverClassName}")
        private String driverClassName;
        @Value("${mybatis.url}")
        private String url;
        @Value("${mybatis.username}")
        private String username;
        @Value("${mybatis.password}")
        private String password;
        @Value("${mybatis.typeAliasesPackages}")
        private String typeAliasesPackages;
        @Value("${mybatis.mapperLocations}")
        private String mapperLocations;
    }
    
    public class MyBatisAutoConfiguration {
    
        @Autowired
        private MybatisProperties mybatisProperties;
    
        @Bean
        public DataSource dataSource() {
            DruidDataSource dataSource = new DruidDataSource();
            dataSource.setDriverClassName(mybatisProperties.getDriverClassName());
            dataSource.setUrl(mybatisProperties.getUrl());
            dataSource.setUsername(mybatisProperties.getUsername());
            dataSource.setPassword(mybatisProperties.getPassword());
            return dataSource;
        }
    
        @Bean
        public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(dataSource);
            sqlSessionFactoryBean.setTypeAliasesPackage(mybatisProperties.getTypeAliasesPackages());
            //sqlSessionFactoryBean.setMapperLocations(new ClassPathResource("UserDAOMapper.xml"));
    
            try {
                ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
                Resource[] resources = resolver.getResources(mybatisProperties.getMapperLocations());
                sqlSessionFactoryBean.setMapperLocations(resources);
            } catch (IOException e) {
                e.printStackTrace();
            }
    
            return sqlSessionFactoryBean;
        }
    }
    
    
10. 純註解版事務程式設計
1. 原始物件 XXXService
   <bean id="userService" class="com.baizhiedu.service.UserServiceImpl">
     <property name="userDAO" ref="userDAO"/>
   </bean>

   @Service
   public class UserServiceImpl implements UserService{
         @Autowired
         private UserDAO userDAO;
   }

2. 額外功能
   <!--DataSourceTransactionManager-->
    <bean id="dataSourceTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
      <property name="dataSource" ref="dataSource"/>
    </bean>
    
    @Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
          DataSourceTransactionManager dstm = new DataSourceTransactionManager();
          dstm.setDataSource(dataSource);
          return dstm 
    }

3. 事務屬性
    @Transactional
    @Service
    public class UserServiceImpl implements UserService {
        @Autowired
        private UserDAO userDAO;

4. 基於Schema的事務配置 
   <tx:annotation-driven transaction-manager="dataSourceTransactionManager"/>
   @EnableTransactionManager ---> 配置Bean
1. ApplicationContext ctx = new AnnotationConfigApplicationContext("com.baizhiedu.mybatis");
   SpringBoot 實現思想
2. 註解版MVC整合,SpringMVC中進行詳細講解
   SpringMyBatis --->DAO  事務基於註解 --> Service   Controller 
   org.springframework.web.context.ContextLoaderListener ---> XML工廠 無法提供 new AnnotationConfigApplicationContext
11. Spring框架中YML的使用
1. 什麼是YML
YML(YAML)是一種新形式的配置檔案,比XML更簡單,比Properties更強大。

YAML is a nice human-readable format for configuration, and it has some useful hierarchical properties. It's more or less a superset of JSON, so it has a lot of similar features.
2. Properties進行配置問題
1. Properties表達過於繁瑣,無法表達資料的內在聯絡. 
2. Properties無法表達物件 集合型別
3. YML語法簡介
1. 定義yml檔案 
   xxx.yml xxx.yaml
2. 語法
   1. 基本語法
      name: suns
      password: 123456
   2. 物件概念 
      account: 
         id: 1
         password: 123456
   3. 定義集合 
      service: 
         - 11111
         - 22222
4. Spring與YML整合思路的分析
1. 準備yml配置檔案 
   init.yml
   name: suns
   password: 123456
2. 讀取yml 轉換成 Properties
   YamlPropertiesFactoryBean.setResources( yml配置檔案的路徑 ) new ClassPathResource();
   YamlPropertiesFactoryBean.getObject() ---> Properties 
3. 應用PropertySourcesPlaceholderConfigurer
   PropertySourcesPlaceholderConfigurer.setProperties();
4. 類中 @Value註解 注入 
5. Spring與YML整合編碼
  • 環境搭建

    <dependency>
      <groupId>org.yaml</groupId>
      <artifactId>snakeyaml</artifactId>
      <version>1.23</version>
    </dependency>
    最低版本 1.18 
    
  • 編碼

    1. 準備yml配置檔案
    2. 配置Bean中操作 完成YAML讀取 與 PropertySourcePlaceholderConfigure的建立 
        @Bean
        public PropertySourcesPlaceholderConfigurer configurer() {
            YamlPropertiesFactoryBean yamlPropertiesFactoryBean = new YamlPropertiesFactoryBean();
            yamlPropertiesFactoryBean.setResources(new ClassPathResource("init.yml"));
            Properties properties = yamlPropertiesFactoryBean.getObject();
    
            PropertySourcesPlaceholderConfigurer configurer = new PropertySourcesPlaceholderConfigurer();
            configurer.setProperties(properties);
            return configurer;
        }
    3. 類 加入 @Value註解 
    
6. Spring與YML整合的問題
1. 集合處理的問題
   SpringEL表示式解決
   @Value("#{'${list}'.split(',')}")
2. 物件型別的YAML進行配置時 過於繁瑣 
   @Value("${account.name}")
   
SpringBoot  @ConfigurationProperties