Spring注解开发初级

注解驱动

意义:将繁杂的配置文件进行了简化,提高了开发效率

弊端:对于第三方资源的引入变得复杂,必须通过部分代码实现第三方资源的引用

常用注解

1.启动注解功能

  • 配置文件中启动注解,记载类中配置的注解项

 <!--注解总开关-->
 <context:component-scan base-package="com.itheima"/>
  • 说明

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

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

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

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

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

  • 注意:

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

    • 从开发效率上来说注解优于XML配置文件

2.bean对象的定义

  • 注解名称:@Component

  • 类别:类注解(定义在类上)

  • 作用:设置改类为Spring管理的bean

  • 如:

     //引号中填写别名
     @Component("userService")
     public class UserServiceImpl implements UserService {}

     

  • 拓展(重点)

    • @Controller(表现层)

    • @Service(控制层)

    • @Repository(数据层)

      这三种注解在三层架构开发中常用,功能与@Component相同

 

3.bean对象的作用域

  • 注解名称:@Scope

  • 类别:类注解(定义在类上)

  • 作用:设置bean对象的scope属性(单个对象"singleton",多个对象"prototype")

  • 如:

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

4.bean的是生命周期

  • 注解名称:@PostConstruct(初始化)、@PreDestroy(销毁)

  • 类别:方法注解(方法定义上方)

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

  • 如:

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

 

5.加载第三方资源

  • 注解名称:@Bean

  • 类别:方法注解(方法定义上方)

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

  • 如:

     @Bean("dataSource")
     public DruidDataSource createDataSource() {    
         return ……;  
     }

     

  • 说明:

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

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

    • @Bean所在的类必须被spring扫描加载,否则该注解无法生效,即类上加 @Component

 

6.bean的非引用属性注入

  • 注解名称:@Value

  • 类别:属性注解、方法注解 (属性定义上方,set方法定义上方 )

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

  • 如:

//引号内添加你想要赋的值
@Value("zhangsan")
private String username;
  • 说明
    • value值仅支持非引用数据类型
    • value支持SpEL,即可通过${}或者#{}获取值
    • @Value注解添加在属性上方可以省去set方法的书写
    • @Value注解支持读取properties文件中的属性值,但必须先将文件引用到类中(方法如下方properties文件加载)

7.bean引用类型属性的注入

  • 注解名称:@Autowired、@Qualifier

  • 类别:属性注解、方法注解(属性定义上方,方法定义上方)

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

//required:定义该属性是否允许为null
//自动加载 默认为false
@Autowired(required = false)
private UserDao userDao;
  • 说明:

    • @Autowired默认按类型装配

    • 指定@Qualifier后可以指定自动装配的bean的id

//引号中添加你想然让它加载的类别名
@Qualifier("userDao")
private UserDao userDao;

8.bean装配优先级配置

  • 注解名称:@Primary

  • 类别:类注解(定义类上方)

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

  • 如:

@Primary
public class ClassName{}
  • 说明:

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

9.加载properties文件

  • 注解名称:@PropertySource

  • 类别:类注解(定义类上方)

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

  • 如:

//加载多个配置文件时,需要将多个文件名添加到数组中,即  {“文件1”,“文件2”...}
@PropertySource(value={"classpath:jdbc.properties","classpath:abc.properties"},
ignoreResourceNotFound = true)
public class ClassName {
    @Value("${propertiesAttributeName}")
    private String attributeName;
}
  • 说明:

    • 不支持*通配格式

    • 一旦加载,所有spring控制的bean中均可使用对应属性

  • 相关属性

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

    • ignoreResourceNotFound:如果资源未找到,是否忽略,默认为false

10.纯注解格式

  • 注解名称:@Configuration、@ComponentScan

  • 类别:类注解(定义类上方)

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

  • 如:

//启动Spring
@Configuration
//扫描所有包
@ComponentScan("scanPackageName")

public class SpringConfigClassName{
}
  • 说明:

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

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

  • 拓展(AnnotationConfigApplicationContext  说明)

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

    • 当配置类作为 AnnotationConfigApplicationContext 对象创建的参数时,@Configuration注解可以不写

AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);

bean加载控制(依赖控制)

1.@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

  • 应用场景

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

2.@Order

  • 名称:@Order

  • 类型:配置类注解

    @Lazy
    public class ClassName {
    }

     

  • 位置:配置类定义的位置(类上

  • 作用:控制配置类的加载顺序,其中值越小优先级越高

  • 范例:

@Order(1)//值越小优先级越高
public class SpringConfigClassName {
}
  • 应用场景

    • 多个种类的配置出现后,优先加载系统级的,然后加载业务级的

3.@Lazy

  • 类型:类注解、方法注解

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

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

  • 范例:

@Lazy
public class ClassName {
}
  • 应用场景
    • 某个业务灾难出现后对应的应急预案处理bean可以延迟加载

整合第三方技术(常用)

1.注解整合mybatis

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

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

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

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

  • 实现

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

    • 业务类使用@Service声明bean,使用@Autowired注入对象

    • 编写Spring配置类:SpringConfig,并加载properties文件

      @Configuration
      @PropertySource("classpath:jdbc.properties")
      public class SpringConfig {
      }
    • 建立配置文件JDBCConfig与MyBatisConfig类,并将其导入到核心配置类SpringConfig

      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(value = "dataSource")
          public DataSource getDataSource(){
              DruidDataSource ds = new DruidDataSource();
              ds.setDriverClassName(driver);
              ds.setUrl(url);
              ds.setUsername(userName);
              ds.setPassword(password);
              return ds;
          }
      }
      public class MyBatisConfig {
      
          @Bean
          public SqlSessionFactoryBean getSqlSessionFactoryBean(@Autowired DataSource dataSource){
              SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean();
              ssfb.setTypeAliasesPackage("实体类所在包路径");
              ssfb.setDataSource(dataSource);
              return ssfb;
          }
      
          @Bean
          public MapperScannerConfigurer getMapperScannerConfigurer(){
              MapperScannerConfigurer msc = new MapperScannerConfigurer();
              msc.setBasePackage("数据层所在包路径");
              return msc;
          }
      
      }
    • 开启注解扫描,将JDBCConfig与MyBatisConfig类导入到核心配置类SpringConfig中

      @Configuration
      @ComponentScan("项目所在包名(全部包)")
      @PropertySource("classpath:jdbc.properties")
      //导入JDBCConfig与MyBatisConfig类
      @Import({JDBCConfig.class,MyBatisConfig.class})
      public class SpringConfig {
      }
    • 使用AnnotationConfigApplicationContext对象加载配置项

      public class Test{ 
          public static void main(String[] args) {
              ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
              //通过getBean()方法获取控制层对象
          }
      }

2.注解整合Junit

  • 导入Spring整合Junit坐标,从Spring5.0以后,要求Junit的版本必须是4.12及以上
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.12</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.9.RELEASE</version>
</dependency>
  • Spring接管Junit的运行权,使用Spring专用的Junit类加载器
@RunWith(SpringJUnit4ClassRunner.class)
  • 加载Spring配置类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class Test {
    @Test
    public void testSave() {}
}

IoC底层核心原理

  • BeanFactory接口

  • HierarchicalBeanFactory接口

  • AutowireCapableBeanFactory接口

  • ListableBeanFactory

1.组件扫描器

开发过程中,需要根据需求加载必要的bean,排除指定bean

2.设定组件扫描加载过滤器

  • 名称:@ComponentScan

  • 类型:类注解

  • 位置:类定义上方

  • 作用:设置spring配置加载类扫描规则

  • 范例:

    @ComponentScan(
        value="资源包名",	           //设置基础扫描路径
        excludeFilters =                   //设置过滤规则,当前为排除过滤
    	@ComponentScan.Filter(            //设置过滤器
    	    type= FilterType.ANNOTATION,  //设置过滤方式为按照注解进行过滤
    	    classes=Service.class)     //设置具体的过滤项,过滤所有@Service修饰的bean
        )
  • 属性

    • includeFilters:设置包含性过滤器

    • excludeFilters:设置排除性过滤器

    • type:设置过滤器类型:ANNOTATION, CUSTOM

3.自定义组件过滤器

  • 名称:TypeFilter

  • 类型:接口

  • 作用:自定义类型过滤器

  • 编写自定义过滤器

    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("所要拦截的类名")){
                return true;
            }
            return false;
        }
    }
  • 使用自定义过滤器:设置排除bean,排除的规则是自定义规则(FilterType.CUSTOM),具体的规则定义为(MyTypeFilter.class)

4.自定义导入器

  • 企业开发过程中,通常需要配置大量的bean,需要一种快速高效配置大量bean的方式

  • 实现接口ImportSelector

  • 名称:ImportSelector

  • 类型:接口

  • 作用:自定义bean导入器

  • 范例:

      public class MyImportSelector implements ImportSelector {
        public String[] selectImports(AnnotationMetadata icm) {
              return new String[]{"所要引入类全名"};
          }
      }
    
    
    //在SpringConfig类中导入
    @Configuration
    @ComponentScan("com.itheima")
    @Import(MyImportSelector.class)
    public class SpringConfig {
    }
  • 拓展

    • 从properties文件读取需要导入的单个类

      //#1.加载import.properties文件中的单个类名
      //className=com.itheima.dao.impl.BookDaoImpl
       
      public class MyImportSelector implements ImportSelector {
            @Override
            public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        	    //2.加载import.properties文件中的单个类名
              	ResourceBundle bundle = ResourceBundle.getBundle("import");
                String className = bundle.getString("className");
                return new String[] {className};
            }
        }
    • 从properties文件读取需要导入的多个类

      //#1.加载import.properties文件中的多个类名
      // className=com.itheima.dao.impl.BookDaoImpl,com.itheima.dao.impl.AccountDaoImpl
      
      
      
      
      public class MyImportSelector implements ImportSelector {
            @Override
            public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        //      2.加载import.properties文件中的多个类名
                ResourceBundle bundle = ResourceBundle.getBundle("import");
                String className = bundle.getString("className");
                return className.split(",");
            }
        }
    • 从properties文件读取需要导入的指定包下的所有类:使用自定义的CustomerImportSelector (实现步骤自行百度)

5.bean初始化过程解析

  • 图解

bean初始化过程

  • BeanFactoryPostProcessor

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

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

  • BeanPostProcessor

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

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

  • InitializingBean

    • 作用:定义了每个bean的初始化前进行的动作,属于非统一性动作,用于对bean进行创建前业务处理

    • 运行时机:当前操作伴随着任意一个bean的创建过程,保障其个性化业务处理

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值