Spring_IoC注解

Spring注解开发

一,注解驱动的意义

1,注解开发的作用与弊端

⚫ 为了达成注解驱动的目的,可能会将原先很简单的书写,变的更加复杂

⚫ XML中配置第三方开发的资源是很方便的,但使用注解驱动无法在第三方开发的资源中进行编辑,因此会增大开发工作量

二,常用注解

1,bean定义常用注解(定义,作用范围,生命周期)

  • 启动注解功能

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

      <context:component-scan base-package="packageName"/>
      <!--无论xml配置还是注解格式,最终都是将资源加载到IoC容器中-->
      

      ⚫ 说明:

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

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

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

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

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

      ⚫ 注意:

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

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

  • bean的定义

    ⚫ 名称:@Component @Controller @Service @Repository

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

    ⚫ 作用:设置该类为spring管理的bean

    ⚫ 范例: 定义bean后面加上bean的id

    @component("bookDao")
    public class BookDaoImpl implements BookDao{
        public void save(){
            sout("running...")
        }
    }
    

    ⚫ 说明:

    ◆ @Controller、@Service 、@Repository是@Component的衍生注解,功能同@Component

    ⚫ 相关属性

    ◆ value(默认):定义bean的访问id,可以默认不写value=

  • 重点:id默认不写时,他会扫描时候会自动,让他的id是类名首字母小写(推荐这样,Component后面不写id,自己测试和getBean时就直接用需要加载的bean的类名首字母小写作为id就行,就是所属数据类型)

  • bean的作用域

    ⚫ 名称:@Scope

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

    ⚫ 作用:设置该类作为bean对应的scope属性

    ⚫ 范例:

    @Scope("prototype")
    public class ClassName{}
    

    ⚫ 相关属性

    ◆ value(默认):定义bean的作用域,默认为singleton

  • bean的生命周期

    ⚫ 名称:@PostConstruct、@PreDestroy

    ⚫ 类型:方法注解

    ⚫ 位置:方法定义上方

    ⚫ 作用:设置该类作为bean对应的生命周期方法

    ⚫ 范例:

    @PostConstruct
    public void init() { 
    System.out.println("init...");
    }
    

2,注解配置第三方资源(工厂加载bean的形式)

  • ⚫ 名称:@Bean

    ⚫ 类型:方法注解

    ⚫ 位置:方法定义上方

    ⚫ 作用:设置该方法的返回值作为spring管理的bean

    ⚫ 范例:

    @Bean("dataSource")
    public DruidDataSource createDataSource() { 
        DruidDataSource ds=new DruidDataSource();
        ds.setDriverClassName("com.mysql.jdbc.Driver");
        ...
        return ds;    
       }
    

    ⚫ 说明:

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

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

    @Bean所在的类必须被spring扫描加载,否则该注解无法生效 (主配置文件中,类上方添加import注解)

    ⚫ 相关属性

    ◆ value(默认):定义bean的访问id

3,属性注入常用注解

  • bean的非引用类型属性注入

    ⚫ 名称:@Value

    ⚫ 类型:属性注解、方法注解

    ⚫ 位置:属性定义上方,方法定义上方

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

    ⚫ 范例:

    @Value("${jdbc.username}")
    private String username;
    

    ⚫ 说明:

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

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

    ◆ value值支持SpEL

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

    ⚫ 相关属性

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

    ————————————————————————

  • bean的引用类型属性注入

    ⚫ 名称:@Autowired、@Qualifier

    ⚫ 类型:属性注解、方法注解

    ⚫ 位置:属性定义上方,方法定义上方

    ⚫ 作用:设置对应属性的对象或对方法进行引用类型传参

    ⚫ 范例:

    @Autowried(required=false)
    @Qualifier("userDao")
    private UserDao userDao
    

    ⚫ 说明:

    ◆ 如果所需要bean的component注解没有带上id,那么**@Autowired默认按类型装配,装配不了就会按类名的首字母小写来装配。**

    如果要指定id,@Qualifier后可以指定自动装配的bean的id

    • @Autowied能正常使用

    ⚫ 相关属性

    ◆ required:定义该属性是否允许为null

    ————————————————————————

  • 名称:@Primary

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

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

    ⚫ 范例:

    @Primary
    public class ClassName{}
    

    ⚫ 说明:

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

    ————————————————————————

  • ⚫ 名称:@Inject、@Named、@Resource

    ⚫ 说明:

    ◆ @Inject与@Named是JSR330规范中的注解,功能与@Autowired和@Qualifier完全相同,适用于不同架构场景 @Inject对应@Autowried

    ◆ @Resource是JSR250规范中的注解,可以简化书写格式

    ⚫ @Resource相关属性

    ◆ name:设置注入的bean的id

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

4,加载properties文件中的属性

  • ⚫ 名称:@PropertySource

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

    ⚫ 作用:加载properties文件中的属性值

    ⚫ 范例:

    @PropertySource(value = "classpath:filename.properties")
    public class ClassName {
    @Value("${propertiesAttributeName}")
    private String attributeName; 
    }
    

    ⚫ 说明:

    ◆ **不支持*通配格式,**一旦加载,所有spring控制的bean中均可使用对应属性值

    有多个的话可以写成数组形式eg:

    @Component
    @Primary
    @PropertySource({"classpath:jdbc.properties","classpath:abc.properties"})
    public class BookDaoImpl implements BookDao {
        @Value("${jdbc.username}")
        private String userName;
        @Value("${jdbc.password}")
        private String password;
    }
    

    ⚫ 相关属性

    ◆ value(默认):设置加载的properties文件名

    ◆ ignoreResourceNotFound:如果资源未找到,是否忽略,默认为false,加这个第二属性

    @PropertySource(value={"classpath:jdbc.properties","classpath:abc.properties"}, ignoreResourceNotFound=true)
    

5,纯注解驱动制作

  • ⚫ 名称:@Configuration、@ComponentScan

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

    ⚫ 作用:设置当前类为spring核心配置加载类

    ⚫ 范例:

    @Configuration
    @ComponentScan("scanPackageName")
    public class springConfigClassName{
    }
    
    • 就是说写了这个之后就可以把applicationContext.xml删掉了。完成所谓的纯注解开发

    ⚫ 说明:

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

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

    • 测试中,加载纯注解格式上下文对象,需要使用AnnotationConfigApplicationContext

      AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
      

6,导入第三方资源对应的配置类

  • 第三方bean配置与管理

    ⚫ 名称:@Import

    ⚫ 类型:类注解

    ⚫ 位置:类定义上方

    ⚫ 作用:导入第三方bean作为spring控制的资源 ,也可以导入其他资源

    ⚫ 范例:也可以把第三方资源直接写到主配置类的下面

    @Configuration
    @ComponentScan("com.itheima")
    @Improt({JDBCConfig.class,abc.class})
    public class springConfig{
    }
    
  • ⚫ 说明:

    @Import注解在同一个类上,仅允许添加一次(建议加在主配置类中),如果需要导入多个,使用数组的形式进行设定

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

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

7,bean加载控制

  • 依赖加载

    ⚫ 名称:@DependsOn

    ⚫ 类型:类注解方法注解

    ⚫ 位置:bean定义的位置(类上或方法上)

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

    ⚫ 范例:

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

    ⚫ 说明:

    • 配置在方法上,使@DependsOn指定的bean优先于@Bean配置的bean进行加载

    • 配置在类上,使@DependsOn指定的bean优先于当前类中所有@Bean配置的bean进行加载

    • 配置在类上,使@DependsOn指定的bean优先于@Component等配置的bean进行加载

    ⚫ 相关属性

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

      ——————————————————

  • ⚫ 名称:@Order

    ⚫ 类型:配置类注解

    ⚫ 位置:配置类定义的位置(类上)

    ⚫ 作用:控制配置类的加载顺序

    ⚫ 范例:

    @Order(1)
    public class SpringConfigClassName { }
    

    ————————————————

  • ⚫ 名称:@Lazy

    ⚫ 类型:类注解**、**方法注解

    ⚫ 位置:bean定义的位置(类上或方法上)

    ⚫ 作用:控制bean的加载时机,使其延迟加载

    ⚫ 范例:

    @Lazy
    public class ClassName { }
    

    ————————————————————

  • 依赖加载应用场景

    ⚫ @DependsOn

    ◆微信订阅号,发布消息和订阅消息的bean的加载顺序控制

    ◆双11活动期间,零点前是结算策略A,零点后是结算策略B,策略B操作的数据为促销数据。策略B

    加载顺序与促销数据的加载顺序

    ⚫ @Lazy

    ◆程序灾难出现后对应的应急预案处理是启动容器时加载时机

    ⚫ @Order

    ◆多个种类的配置出现后,优先加载系统级的,然后加载业务级的,避免细粒度的加载控制

三,整合第三方技术

1,注解整合mybatis分析

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YUdZklHH-1595069560624)(E:\每日讲课笔记\Spring\img\1594808620645.png)]

  • ⚫ 业务类使用注解形式声明bean,属性采用注解注入

    ⚫ 建立独立的配置管理类,分类管理外部资源,根据功能进行分类,并提供对应的方法获取bean

    ⚫ 使用注解形式启动bean扫描,加载所有注解配置的资源(bean)

    ⚫ 使用AnnotationConfigApplicationContext对象加载所有的启动配置类,内部使用导入方式进行关联

  • 整合步骤

      1. 修改mybatis外部配置文件格式为注解格式

      2. 业务类使用@Component声明bean,使用@Autowired注入对象

      3. 建立配置文件JDBCConfig与MyBatisConfig类,并将其导入到核心配置类SpringConfig

      4. 开启注解扫描

      5. 使用AnnotationConfigApplicationContext对象加载配置项

2,注解整合mybatis

  • 包层次结构

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xNCg7rF7-1595069560629)(E:\每日讲课笔记\Spring\img\1594808817946.png)]

  • config

    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")//MyBatisConfig中要用,所以起了一个名字
        public DataSource getDataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName(driver);
            ds.setUrl(url);
            ds.setUsername(userName);
            ds.setPassword(password);
            return ds;
        }
    
    }
    
    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 sqlSessionFactoryBean=new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setTypeAliasesPackage("com.itheima.domain");
            sqlSessionFactoryBean.setDataSource(dataSource);
            return sqlSessionFactoryBean;
        }
        @Bean
        public MapperScannerConfigurer getMapperScannerConfigurer(){
            MapperScannerConfigurer mapperScannerConfigurer=new MapperScannerConfigurer();
            mapperScannerConfigurer.setBasePackage("com.itheima.dao");
            return mapperScannerConfigurer;
        }
    }
    
    
    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})//只能写一个import,多的第三方配置在这用数组表示
    public class SpringConfig {
    }
    
    
  • dao层

    package com.itheima.dao;
    
    import com.itheima.domain.Account;
    import org.apache.ibatis.annotations.Delete;
    import org.apache.ibatis.annotations.Insert;
    import org.apache.ibatis.annotations.Select;
    import org.apache.ibatis.annotations.Update;
    
    import java.util.List;
    
    public interface AccountDao {
    
        @Insert("insert into account(name,money)values(#{name},#{money})")
        void save(Account account);
    
        @Delete("delete from account where id = #{id} ")
        void delete(Integer id);
    
        @Update("update account set name = #{name} , money = #{money} where id = #{id} ")
        void update(Account account);
    
       @Select("select * from account")
        List<Account> findAll();
    
        @Select("select * from account where id = #{id} ")
        Account findById(Integer id);
    }
    
  • domain层

  • package com.itheima.domain;
    
    import java.io.Serializable;
    
    public class Account implements Serializable {
    
        private Integer id;
        private String name;
        private Double money;
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Double getMoney() {
            return money;
        }
    
        public void setMoney(Double money) {
            this.money = money;
        }
    
        @Override
        public String toString() {
            return "Account{" +
                    "id=" + id +
                    ", name='" + name + '\'' +
                    ", money=" + money +
                    '}';
        }
    }
    
    
  • service层

    package com.itheima.service.impl;
    //实现类
    import com.itheima.dao.AccountDao;
    import com.itheima.domain.Account;
    import com.itheima.service.AccountService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    
    import java.util.List;
    @Component("accountService")
    public class AccountServiceImpl implements AccountService {
    
        @Autowired
        private AccountDao accountDao;
    
        public void save(Account account) {
            accountDao.save(account);
        }
    
        public void update(Account account){
            accountDao.update(account);
        }
    
        public void delete(Integer id) {
            accountDao.delete(id);
        }
    
        public Account findById(Integer id) {
            return accountDao.findById(id);
        }
    
        public List<Account> findAll() {
            return accountDao.findAll();
        }
    }
    
    package com.itheima.service;
    //接口
    import com.itheima.domain.Account;
    
    import java.util.List;
    
    public interface AccountService {
    
        void save(Account account);
    
        void delete(Integer id);
    
        void update(Account account);
    
        List<Account> findAll();
    
        Account findById(Integer id);
    
    }
    
  • properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://192.168.23.129:3306/db14
    jdbc.username=root
    jdbc.password=root
    
  • 测试类

    import com.alibaba.druid.pool.DruidDataSource;
    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;
    import java.util.List;
    
    public class App {
        public static void main(String[] args) {
          ApplicationContext ctx=new AnnotationConfigApplicationContext(SpringConfig.class);
            AccountService accountService = (AccountService) ctx.getBean("accountService");
            List<Account> ac = accountService.findAll();
            System.out.println(ac);
    
        }
    }
    

3,注解整合Junit

  • 如何在Junit中使用spring中的资源呢?

    • Spring接管Junit的运行权,使用Spring专用的Junit类加载器

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

    注意:

    ◆ 从Spring5.0以后,要求Junit的版本必须是4.12及以上

    ◆ Junit仅用于单元测试,不能将Junit的测试类配置成spring的bean,否则该配置将会被打包进入工

    程中

  • ⚫ Spring整合Junit测试用例注解格式

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(classes = SpringConfig.class)
    public class UserServiceTest {
    }
    

四,IoC底层核心原理

1,IoC核心接口

2,组件扫描过滤器

3,自定义导入器

4,自定义注册器

5,bean初始化过程解析

    AccountService accountService = (AccountService) ctx.getBean("accountService");
      List<Account> ac = accountService.findAll();
      System.out.println(ac);

  }

}




### 3,注解整合Junit

- 如何在Junit中使用spring中的资源呢?

-  Spring接管Junit的运行权,使用Spring专用的Junit类加载器 

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

  注意: 

  ◆ 从Spring5.0以后,要求Junit的版本必须是4.12及以上 

  ◆ Junit仅用于单元测试,**不能将Junit的测试类配置成spring的bean**,否则该配置将会被打包进入工 

  程中

- ⚫ Spring整合Junit测试用例注解格式

```java
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class UserServiceTest {
}

四,IoC底层核心原理

1,IoC核心接口

2,组件扫描过滤器

3,自定义导入器

4,自定义注册器

5,bean初始化过程解析

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值