Spring-02

注解开发

学习目标

​ **1)**注解实现类对象的注册到容器:

​ 1.自己定义的类:@Component @Controller @Service @Repository

​ 2.三方类:@Bean 注意: 该注解所在的类必须被 上述注解任意一个所修饰

​ **2)**注解实现属性依赖注入:

​ 1.普通属性:@Value 可以修饰属性 和 set 方法,推荐修饰属性,因为可以不提供setter方法

​ 2.引用类型属性:@Autowired 类型注入 @Qualifier 指定bean id注入,@Resource 可以替代掉 @Autowired @Qualifier, 该注解不加任何属性,默认类型注入;

3)@Primary 作用 (了解):设置类对应的bean按类型装配时优先装配,

注意:@Autowired默认按类型装配,当出现相同类型的bean,使用@Primary提高按类型自动装配的优先级,多个@Primary 会导致优先级设置无效

4) 使用 @Configuration、@ComponentScan 替代 applicationContext.xml 文件

​ **5)**实现框架的整合 (包含Junit)

1.注解反转驱动的弊端

1.1 什么是注解驱动
  • 利用spring提供的注解替代掉xml文件中做的配置,干的活都是一样的
1.2 注解驱动的弊端
  • 为了达成注解驱动的目的,可能会将原先很简单的书写,变的更加复杂,毕竟注解也不是做各种配置都很灵活。

2. 常用注解

2.1 启动注解功能

⚫ 启动注解扫描,加载类中配置的注解项

<context:component-scan base-package="packageName"/>

⚫ 说明:

◆ 在进行包所扫描时,会对配置的包及其子包中所有文件进行扫描

◆ 扫描过程是以文件夹递归迭代的形式进行的

◆ 扫描过程仅读取合法的java文件

◆ 扫描时仅读取spring可识别的注解

◆ 扫描结束后会将可识别的有效注解转化为spring对应的资源加入IoC容器

⚫ 注意:

◆ 无论是注解格式还是XML配置格式,最终都是将资源加载到IoC容器中,差别仅仅是数据读取方式不同

◆ 从加载效率上来说注解优于XML配置文件

//定义bean,后面添加bean的id
@Component("userService")
//@scope默认是单例模式(singleton)即:@scope("singleton")
//1.singleton单例模式,全局有且仅有一个实例
//2.prototype原型模式,每次获取Bean的时候会有一个新的实例
@Scope("singleton")
public class UserServiceImpl implements UserService {
    
    //设定bean的生命周期-销毁
    @PreDestroy
    public void destroy(){
        System.out.println("user service destroy...");
    }
    //设定bean的生命周期-新建
    @PostConstruct
    public void init(){
        System.out.println("user service init...");
    }
}
package com.itheima;
public class App {
    public static void main(String[] args) {
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        UserService userService = (UserService) ctx.getBean("userService");
        userService.save();
    }
}
2.2 加载第三方资源

⚫ 位置:方法定义上方

⚫ 说明:

◆ 因为第三方bean无法在其源码上进行修改,使用@Bean解决第三方bean的引入问题

◆ 该注解用于替代XML配置中的静态工厂与实例工厂创建bean,不区分方法是否为静态或非静态

◆ @Bean所在的类必须被spring扫描加载并被 @Controller、@Service、@Repository @Component所修饰,否则该注解无法生效 。

⚫ 第三方资源注解配置方式 ◆ 需要引用添加名称 ◆ 无需引用省略名称

public class JDBCConfig {

    //定义bean的访问id
    @Bean("dataSource")
    public static DruidDataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("itheima");
        return ds;
    }
}

2.3 非引用类型注入

⚫ 位置:定义属性上方,定义set方法上方 (用的很少)

⚫ 作用:设置对应属性的值或对方法进行传参

⚫ 范例:

@Value("4")
private int num ;
@Value("itheima")
private String version;

⚫ 说明:

◆ value值仅支持非引用类型数据,赋值时对方法的所有参数全部赋值

◆ value值支持读取properties文件中的属性值,通过类属性将properties中数据传入类中

◆ value值支持SpEL

◆ @value注解如果添加在属性上方,可以省略set方法(set方法的目的是为属性赋值)

⚫ 相关属性

◆ value(默认):定义对应的属性值或参数值

2.4 引用类型注入

⚫ 说明:

◆ @Autowired按类型装配, 同一个类型接口最好只有一个实现类

◆ @Autowired按类型装配, 同一个类型接口多个实现类时

1)类型相同:属性名与bean id 保持一致也可以完成注入, 如果没有bean id, 属性名为 实现类 首字母转小写 后的名称,也可注入。

​ **2)类型相同&名称与bean id匹配不上:**按照优先级@Primary完成注入

​ **3)类型相同&名称与bean id匹配不上&优先级一致:**报错

◆ @Qualifier指定自动装配的bean的id

◆ @Resource 可以替代掉 @Autowired @Qualifier 但是不推荐使用,最好还是用spring的注解的完成注入

  • name:设置注入的bean的id

  • type:设置注入的bean的类型,接收的参数为Class类型

  • 什么属性不指定, 默认按照类型注入

@Autowired
@Qualifier("userDao")
private UserDao userDao;

//默认类型注入  指定名称: @Resource(name = "book2")
@Resource
private BookDao bookDao;

@Primary 作用:设置类对应的bean按类型装配时优先装配

@Primary
public class ClassName{}

◆说明:

  • @Autowired默认按类型装配,当出现相同类型的bean,使用@Primary提高按类型自动装配的优先级,多个@Primary 会导致优先级设置无
2.5 加载properties文件

@PropertySource :定义类上方 ,作用:加载properties文件中的属性值

//一般只加载一个配置文件, ${key}
@PropertySource(value={"classpath:jdbc.properties","classpath:abc.properties"},ignoreResourceNotFound = true)
public class BookDaoImpl implements BookDao {
    
    @Value("${jdbc.userName}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

}
2.6 纯注解驱动制作 (重点)

⚫ @Configuration、@ComponentScan 定义在类上方, 作用:设置当前类为spring核心配置加载类, 替代掉applicationContext.xml

@Configuration
@ComponentScan("com.itheima")
public class SpringConfig{
}

⚫ 说明:

◆ 核心配合类用于替换spring核心配置文件,此类可以设置空的,不设置变量与属性

◆ bean扫描工作使用注解@ComponentScan替代

⚫ 加载纯注解格式上下文对象,需要使用AnnotationConfigApplicationContext

ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

UserService userService = (UserService) ctx.getBean("userService");
userService.save();
2.7 第三方bean配置与管理

⚫ @Import 定义类上方 , 作用:导入@Bean 所在的类

⚫ 范例:

//当前数组中只有一个值
@Import({JDBCConfig.class})
@ComponentScan("com.itheima")
@Configuration
public class SpringConfig {}

//被导入的类
public class JDBCConfig {
    @Bean("dataSource")
    public static DruidDataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
        ds.setUsername("root");
        ds.setPassword("itheima");
        return ds;
    }
}

⚫ 说明:

◆ @Import注解在同一个类上,仅允许添加一次,如果需要导入多个,使用数组的形式进行设定

◆ 在被导入的类中可以继续使用@Import导入其他资源(了解)

◆ @Bean所在的类可以使用导入的形式进入spring容器,无需声明为bean

2.8 bean加载控制 (了解)
2.8.1 @DependsOn(“其他beanid”)

⚫ 定义在类上 ,作用:控制bean的加载顺序,使其指定bean加载完毕后再加载

范例:

@DependsOn("beanId") public class ClassName {
}

**属性:**value(默认):设置当前bean所依赖的bean的id

注意

1、Spring管理的bean默认都是单例模式(singleton)

2、实例化对象应该顺序化的,比如A依赖B,B依赖C,C依赖D…

3、一个bean可以依赖多个bean,可以通过逗号(",")来定义多个依赖对象:

@DependsOn("beanId1, beanId2, beanId3") public class ClassName {
}
2.8.2 @Order(“数字”)

⚫ 定义类上 , 作用:控制@Configuration修饰类的加载顺序

⚫ 范例:

@Order(1)
public class SpringConfigClassName {
}

注意

  1. @Order 的数字值 越大优先级越低,例如 1 的优先级大于 2
  2. 优先级越大的类中 @bean 修饰的方法优先注入。
2.8.3 @Lazy

说明:

1)用于指定单例bean实例化的时机,在没有指定此注解时,单例会在容器初始化时就被创建。而当使用此注解后,单例对象的创建时机会在该bean在被第一次使用时创建,并且只创建一次。第二次及以后获取使用就不再创建。

2)在实际开发场景中,并不是所有bean都要一开始就被创建的,有些可以等到使用时才创建。此时就可以使用该注解实现。

3)此注解只对单例bean有用,原型bean时此注解不起作用。

实例:

@Lazy注解作用于类上时,通常与@Component及其衍生注解配合使用。

//与@component配合使用
@Component
@Lazy
public class UserService {

    public UserService(){
        System.out.println("userService创建了");
    }
}

@Lazy注解作用于方法上时,通常与@Bean注解配合使用。

@Configuration
@ComponentScan(basePackages = "lazyDemo")
public class SpringConfig {

    @Bean
    @Lazy
    //与@Bean注解配合使用
    public UserService userService1(){
        return new UserService();
    }
}

3. 整合第三方技术

步骤:

  1. 修改mybatis外部配置文件格式为注解格式
  2. 业务类使用@Component声明bean,使用@Autowired注入对象
  3. 建立配置文件JDBCConfig与MyBatisConfig类,并将其导入到核心配置类SpringConfig
  4. 开启注解扫描
  5. 使用AnnotationConfigApplicationContext对象加载配置项
App.java
import com.itheima.config.SpringConfig;
import com.itheima.domain.Account;
import com.itheima.service.AccountService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
    public static void main(String[] args) {

        ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountService accountService = (AccountService) ctx.getBean("accountService");
        Account ac = accountService.findById(2);
        System.out.println(ac);
    }
}

SpringConfig.java
package com.itheima.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JDBCConfig.class,MyBatisConfig.class})
public class SpringConfig {
}

JDBCConfig.java
package com.itheima.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class JDBCConfig {
    @Value("${jdbc.driver}")
    private String driver;
    @Value("${jdbc.url}")
    private String url;
    @Value("${jdbc.username}")
    private String userName;
    @Value("${jdbc.password}")
    private String password;

    @Bean("dataSource")
    public DataSource getDataSource(){
        DruidDataSource ds = new DruidDataSource();
        ds.setDriverClassName(driver);
        ds.setUrl(url);
        ds.setUsername(userName);
        ds.setPassword(password);
        return ds;
    }
}

MyBatisConfig.java
package com.itheima.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class MyBatisConfig {

    @Bean
    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
        SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
        ssfb.setTypeAliasesPackage("com.itheima.domain");
        ssfb.setDataSource(dataSource);
        return ssfb;
    }

    @Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
        msc.setBasePackage("com.itheima.dao");
        return msc;
    }

}

注解整合Junit
  1. Spring接管Junit的运行权,使用Spring专用的Junit类加载器

  2. 为Junit测试用例设定对应的spring容器

注意:
◆ 从Spring5.0以后,要求Junit的版本必须是4.12及以上 ◆ Junit仅用于单元测试,不能将Junit的测试类配置成spring的bean,否则该配置将会被打包进入工 程中

UserServiceTest.java
package com.itheima.service;

import com.itheima.config.SpringConfig;
import com.itheima.domain.Account;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import java.util.List;

//设定spring专用的类加载器
@RunWith(SpringJUnit4ClassRunner.class)
//设定加载的spring上下文对应的配置
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {

    @Autowired
    private AccountService accountService;

    @Test
    public void testFindById(){
        Account ac = accountService.findById(2);
//        System.out.println(ac);
        Assert.assertEquals("Jock1",ac.getName());
    }

    @Test
    public void testFindAll(){
        List<Account> list = accountService.findAll();
        Assert.assertEquals(3,list.size());
    }

}

4. IoC底层核心原理

4.1 设定组件扫描加载过滤器

@ComponentScan是告诉Spring 哪个packages 的用注解标识的类 会被spring自动扫描并且装入bean容器。

excludeFilters:指定不适合组件扫描的类型。

includeFilters:指定哪些类型有资格用于组件扫描。

注解过滤
  • 过滤掉指定注解,让其不发挥具体功能
@ComponentScan(
    value="com.itheima", // 设置基础扫描路径
    excludeFilters = // 设置过滤规则,当前为排除过滤
    @ComponentScan.Filter( // 设置过滤器
    type= FilterType.ANNOTATION, // 设置过滤方式为按照注解进行过滤
    classes=Repository.class) // 设置具体的过滤项,过滤所有 @Repository 修饰的 bean
)
自定义过滤器
  • public boolean match() 方法 返回false 不拦截,true 为拦截。
//2.设置排除bean,排除的规则是自定义规则(FilterType.CUSTOM),具体的规则定义为(MyTypeFilter.class)
@ComponentScan(
        value = "com.itheima",
        excludeFilters = @ComponentScan.Filter(
                type= FilterType.CUSTOM,
                classes = MyTypeFilter.class
        )
)
public class SpringConfig {
}

/************************** 自定义过滤器 *******************/
package config.filter;

import org.springframework.core.type.ClassMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class MyTypeFilter implements TypeFilter {
    @Override
    //加载的类满足要求,匹配成功
    public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
        //通过参数获取加载的类的元数据
        ClassMetadata classMetadata = metadataReader.getClassMetadata();
        //通过类的元数据获取类的名称
        String className = classMetadata.getClassName();
        //如果加载的类名满足过滤器要求,返回匹配成功
        if(className.equals("com.itheima.service.impl.UserServiceImpl")){
            //返回true表示匹配成功,返回false表示匹配失败。此处仅确认匹配结果,不会确认是排除还是加入,排除/加入由配置项决定,与此处无关
            return true;
        }
        return false;
    }
}
4.2 自定义导入器性
  • 自定义导入器-可以帮助我们将指定类(没被@Service修饰)注入到bean容器中,功能类似@Bean。
SpringConfig.java
//自定义导入器
@Import(MyImportSelector.class)
public class SpringConfig {
}
import.properties
#2.加载import.properties文件中的单个类名
#className=com.itheima.dao.impl.BookDaoImpl

#3.加载import.properties文件中的多个类名
#className=com.itheima.dao.impl.BookDaoImpl,com.itheima.dao.impl.AccountDaoImpl

path=com.itheima.dao.impl.*

MyImportSelector.java
package config.selector;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

import java.util.ResourceBundle;

public class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
//      1.编程形式加载一个类
//      return new String[]{"com.itheima.dao.impl.BookDaoImpl"};

//      2.加载import.properties文件中的单个类名
//      ResourceBundle bundle = ResourceBundle.getBundle("import");
//      String className = bundle.getString("className");

//      3.加载import.properties文件中的多个类名
        ResourceBundle bundle = ResourceBundle.getBundle("import");
        String className = bundle.getString("className");
        return className.split(",");
    }
}

4.3 自定义注册器
  • 功能要比 @ComponentScan(“com.itheima”) 更强大,@ComponentScan(“com.itheima”)只会扫描包下被 @Service 等注解修饰的类注入到bean容器中, 而我们注册器配置的包扫描可以将指定包下所有类(未被注解修饰也算)都注入到bean容器中。
  • 扩展的 CustomeImportBeanDefinitionRegistrar 可以给指定包下的所有类(未被@Service等注解修饰,注入到spring bean容器中。
SpringConfig.java
//自定义注册器
@Import(MyImportBeanDefinitionRegistrar.class)
public class SpringConfig {
}
MyImportBeanDefinitionRegistrar.java
package config.registrar;

import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.TypeFilter;

import java.io.IOException;

public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        //自定义注册器
        //1.开启类路径bean定义扫描器,需要参数bean定义注册器BeanDefinitionRegistry,需要制定是否使用默认类型过滤器
        ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry,false);
        //2.添加包含性加载类型过滤器(可选,也可以设置为排除性加载类型过滤器)
        scanner.addIncludeFilter(new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
                //所有匹配全部成功,此处应该添加实际的业务判定条件
                return true;
            }
        });
        //设置扫描路径
        scanner.scan("com.itheima");
    }
}

4.4 bean初始化过程解析
bean初始化过程解析

⚫ BeanFactoryPostProcessor

​ ◆ 作用:定义了在bean工厂对象创建后,bean对象创建前执行的动作,用于对工厂进行创建后业务处理

​ ◆ 运行时机:当前操作用于对工厂进行处理,仅运行一次

⚫ BeanPostProcessor

​ ◆ 作用:定义了所有bean初始化前后进行的统一动作,用于对bean进行创建前业务处理与创建后业务处理

​ ◆ 运行时机:当前操作伴随着每个bean的创建过程,每次创建bean均运行该操作

SpringConfig.java
@Import({MyImportBeanDefinitionRegistrar.class, MyBeanFactory.class, MyBean.class})
public class SpringConfig {
}
MyBeanFactory.java
package config.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;

public class MyBeanFactory implements BeanFactoryPostProcessor {
    @Override
    //工厂后处理bean接口核心操作
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("bean工厂制作好了,还有什么事情需要处理");
    }
}
MyBean.java
package config.postprocessor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

public class MyBean implements BeanPostProcessor {
    @Override
    //所有bean初始化前置操作
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean之前巴拉巴拉");
        System.out.println(beanName);
        return bean;
    }

    @Override
    //所有bean初始化后置操作
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("bean之后巴拉巴拉");
        return bean;
    }
}

5. 容器中注册bean对象形式

1)包扫描 + 组件标注注解
  • @Component @Controller @Service @Repository
  • @ComponentScan(“根包名称”) //com.itheima
2)@Bean
  • 一般在@Configuration 配置类中注册bean对象
  • 多用于注册三方框架中的对象
3)spring提供的FactoryBean
  • FactoryBean 是工厂类接口, 用户通过实现该接口定制实例化 bean 对象

  • 实现Srping提供的FactoryBean, 并保证实现类对象可以注册到bean容器中

4)@Import
  • @Import(自定义类.class), @Import({类1.class, 类2.class, 批量注册类.class, 注册器类.class})

  • 批量注册类: 实现ImportSelector接口

  • 注册器类:实现ImportBeanDefinitionRegistrar接口

6. 注解整合注意事项 (必看)

**目标:**将mybatis javabean别名扫描路径 和 dao 扫描路径配置到jdbc.properties文件中

**但是:**课上 @Bean 注册 MapperScannerConfigurer存在如下问题:

  • //问题:
    MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor使得spring容器会优先处理该bean的注册,导致当前类MyBatisConfig 还没有注入属性(@Value 未工作), 所以 下方 getMapperScannerConfigurer() 方法执行时, 所有@Value 修饰的属性都为空
    
  • //解决办法:
    1. 使用 @MapperScan("com.itheima.dao") 注解替代 @Bean 注册 MapperScannerConfigurer 对象
    2. mybatis-spring 1.3.1 及以下版本不支持 @MapperScan("${mybatis.basePackage}") 这种写法, 升级2.0.3及以上版本即可
    
pom.xml
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <!-- <version>1.3.1</version>-->
    <version>2.0.3</version>
</dependency>
jdbc.properties
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/spring_db
jdbc.username=root
jdbc.password=root

##Mybatis 相关配置
mybatis.typeAliasesPackage=com.itheima.domain
mybatis.basePackage=com.itheima.dao
MyBatisConfig.java
package com.itheima.config;

import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;

/**
 * 课上 @Bean 注册 MapperScannerConfigurer存在如下问题:
 * 问题:MapperScannerConfigurer实现了BeanDefinitionRegistryPostProcessor使得spring容器会优先处理该bean的注册,导致当前类MyBatisConfig 还
 *      没有注入属性(@Value 未工作), 所以 下方 getMapperScannerConfigurer() 方法执行时, 所有@Value 修饰的属性都为空
 *
 * 解决办法:
 *      1. 使用 @MapperScan("com.itheima.dao") 注解替代 @Bean 注册 MapperScannerConfigurer 对象
 *      2. mybatis-spring 1.3.1 及以下版本不支持 @MapperScan("${mybatis.basePackage}") 这种写法, 升级2.0.3及以上版本即可
 */


@MapperScan("${mybatis.basePackage}")
//@MapperScan("com.itheima.dao")
public class MyBatisConfig {


    @Value("${mybatis.typeAliasesPackage}")
    private String typeAliasesPackage;

    @Bean
//    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Qualifier("druidDataSource") DataSource dataSource) throws IOException {
    public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource druidDataSource){

        System.out.println("typeAliasesPackage : " + typeAliasesPackage);

        SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
//        sessionFactory.setTypeAliasesPackage("com.itheima.domain");
        sessionFactory.setTypeAliasesPackage(typeAliasesPackage);
        sessionFactory.setDataSource(druidDataSource);

        /*加载mybatis核心配置文件: 日志 + 分页 */
        sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("classpath:mybatis-page.xml"));

        /* 方式二 配置分页*/
        /*Interceptor pageInterceptor = new PageInterceptor();
        Properties props = new Properties();
        props.setProperty("reasonable", "false");
        props.setProperty("params", "count=countSql");
        pageInterceptor.setProperties(props);
        Interceptor[] plugins = new Interceptor[]{pageInterceptor};
        sessionFactory.setPlugins( plugins );*/

        /*加载xml配置文件*/
//        sessionFactory.setMapperLocations( new PathMatchingResourcePatternResolver().getResources("classpath:mapper/**/*.xml") );

        return sessionFactory;
    }


    /*@Bean
    public MapperScannerConfigurer getMapperScannerConfigurer(){
        System.out.println("basePackage : " + basePackage);
        MapperScannerConfigurer msc = new MapperScannerConfigurer();
//        msc.setBasePackage("com.itheima.dao");
        msc.setBasePackage(basePackage);
        msc.setProcessPropertyPlaceHolders(true);
        return msc;
    }*/

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值