5、Spring_DI注解开发

DI 注解开发

1.目前面临问题

  • 建立 mapper

    public interface EmployeeMapper {
        void save();
    }
    
  • 建立 mapper 实现类

    @Repository
    public class EmployeeMapperImpl implements EmployeeMapper {
        public void save(){
            System.out.println("保存员工信息");
        }
    }
    
  • 建立 service

    public interface IEmployeeService {
        void save();
    }
    
  • 建立 service 实现类

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        private EmployeeMapper employeeMapper;
    
        public void setEmployeeMapper(EmployeeMapper employeeMapper){
            this.employeeMapper = employeeMapper;
        }
        public void save() {
            employeeMapper.save();
        }
    }
    
  • 设置配置类

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    public class DiConfig {
    }
    
  • 出现空指针异常

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oSHnV3L7-1692700773739)(picture/image-20221028160214170.png)]

2.使用类型注入

  • @Autowired按照类型注入

  • 通过构造器注入

    @Autowired
    public EmployeeServiceImpl(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
    
  • 通过setter 方法注入

    @Autowired
    public void setEmployeeMapper(EmployeeMapper employeeMapper) {
        this.employeeMapper = employeeMapper;
    }
    
  • 直接在属性上使用(是以后用得最多的)

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        @Autowired
        private EmployeeMapper employeeMapper;
    
        public void save() {
            employeeMapper.save();
        }
    }
    
    • 注意:不提供setter 方法以及构造器是使用反射创建对象的

      @Test
          public void autowired() throws Exception {
              final Class<?> aClass = Class.forName("cn.sycoder.di.di01.service.impl.EmployeeServiceImpl");
              final Object o = aClass.newInstance();
              final Field[] fields = aClass.getDeclaredFields();
              AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(DiConfig.class);
              final EmployeeMapper bean = context.getBean(EmployeeMapper.class);
              for (Field field : fields) {
                  field.setAccessible(true);
                  field.set(o,bean);
              }
              final EmployeeServiceImpl service = (EmployeeServiceImpl) o;
              service.save();
          }
      
    • 根据类型注入必须只有一个实现类,否则会报错,添加名称也不行

      [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZJHcdvtU-1692700773741)(picture/image-20221028161616168.png)]

  • 属性required=false,如果找不到不会报错

3.使用名称注入

  • @Autowired & @Qualifier

  • @Autowired & @Qualifier必须同时使用,缺一不可

  • 解决刚才出现两个实现类没法注入的问题

  • 配置mapper 并且指定实现类的名称

    public interface EmployeeMapper {
        void save();
    }
    
    @Repository("empMapper2")
    public class EmployeeMapperImpl implements EmployeeMapper {
        public void save(){
            System.out.println("保存员工信息");
        }
    }
    
    @Repository("empMapper1")
    public class EmployeeMapperImpl1 implements EmployeeMapper{
        public void save() {
            System.out.println("save");
        }
    }
    
  • 注入的时候使用名称注入

    @Service
    public class EmployeeServiceImpl implements IEmployeeService {
    
        @Autowired(required = false)
        @Qualifier("empMapper1")
        private EmployeeMapper employeeMapper;
    
        public void save() {
            employeeMapper.save();
        }
    
    }
    

4.简单数据类型注入

  • @Value

    @Component
    public class DbProperties {
        
        @Value("sy")
        private String username;
        @Value("123456")
        private String password;
        
    }
    
  • 硬编码,太垃圾了,需要改成动态

5.注解读取配置文件参数

  • @Value

  • 修改配置类

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    @PropertySource("db.properties")
    public class DiConfig {
    }
    
  • 修改获取方式使用 ${} 的方式

    @Component
    public class DbProperties {
    
        @Value("${username}")
        private String username;
        @Value("${password}")
        private String password;
    
        public void test(){
            System.out.println(username + ":" + password);
        }
    }
    

5.1@PropertySource

  • @PropertySource 加载配置文件

  • 位置:配置类上

  • 作用导入配置文件

  • 对于多个配置文件

    @Configuration
    @ComponentScan("cn.sycoder.di.di01")
    @PropertySource({"db.properties","xx.properties"})
    public class DiConfig {
    }
    

6.注解配置第三方bean

6.1配置 druid

  • 添加依赖

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.2.8</version>
    </dependency>
    
  • 先添加配置类 SpringConfig

    @Configuration
    public class SpringConfig {
    
    
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    
    }
    
  • 传统做法存在硬编码,DataSource 并且没有交给 spring 管理,每次都需要重新新建 DataSource ,并不存在单例一说

    @Test
        public void testDruid(){
            AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
            final SpringConfig bean = context.getBean(SpringConfig.class);
            System.out.println(bean.dataSource());
        }
    

6.2@Bean 配置 druid

  • 使用@Bean 交给 spring 管理

    @Configuration
    public class SpringConfig {
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername("root");
            source.setPassword("123456");
            source.setDriverClassName("com.mysql.cj.jdbc.Driver");
            source.setUrl("jdbc:mysql://localhost:3306/mybatis");
            return source;
        }
    
    }
    
  • 修改配置的硬编码改成软编码

    @Configuration
    @PropertySource("druidDb.properties")
    public class SpringConfig {
        @Value("${jdbc.username}")
        private String username;
        @Value("${jdbc.password}")
        private String password;
        @Value("${jdbc.url}")
        private String url;
        @Value("${jdbc.driverClassName}")
        private String driver;
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    
    }
    
    jdbc.username=root
    jdbc.password=123456
    jdbc.driverClassName=com.mysql.cj.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/mybatis
    
  • @Bean 与 xml 对应

    5、Spring_DI注解开发_第1张图片

7.使用@Import 实现配置导入

  • 目前存在:任何类都配置到配置类里面,不方便管理,也不方便维护

7.1配置 Component 解决

  • @Component

    @Component
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }
    

7.2使用@import

  • 修改druidConfig

    @Configuration
    public class DruidConfig {
        @Value("{jdbc.username}")
        private String username;
        @Value("{jdbc.password}")
        private String password;
        @Value("{jdbc.url}")
        private String url;
        @Value("{jdbc.driverClassName}")
        private String driver;
    
    
        @Bean
        public DataSource dataSource(){
            final DruidDataSource source = new DruidDataSource();
            source.setUsername(username);
            source.setPassword(password);
            source.setDriverClassName(driver);
            source.setUrl(url);
            return source;
        }
    }
    
  • 修改spring配置类

    @Configuration
    @PropertySource("druidDb.properties")
    @Import({DruidConfig.class})
    public class SpringConfig {
    }
    
  • 如果需要传参,只需要将参数交给spring管理就行了

    @Configuration
    public class RepositoryConfig {
         @Bean
         public AccountRepository accountRepository(DataSource dataSource) {
            return new JdbcAccountRepository(dataSource);
         }
    }
    

8.注解开发总结

注解配置 xml 配置 功能说明
@Component
@Controller
@Service
@Repository
bean 标签(id,class) 定义bean
@ComponentScan 扫描包加载bean
@Autowired
@Qualifier
@Value
setter 注入
构造器注入
自动装配
依赖注入
@Bean bean 标签,静态工厂模式,实例工厂模式,FactoryBean 配置第三方bean
@Scope bean 标签中的 scope 属性 设置作用域
@PostConstructor
@PreDestroy
bean 标签中的 init-method / destroy-method 生命周期相关
@Import 导入其它的配置类
@PropertySource({“db.properties”,“xx.properties”}) 导入配置文件

9.lombok 地址

  • lombok学习地址

你可能感兴趣的:(spring,java,后端)