带你了解Spring-IOC注解开发

一、背景-顺应历史潮流

 

随着Springboot开发的流行,我们也开始频繁的使用注解开发,今天理一下常见的Spring-IOC注解。以下代码经过我亲测,有不对的地方望指点纠正

二、使用与测试

 

测试代码的结构:

在开始之前先来一波以前利用xml配置文件创建注入的方法:

新建实体类Person.class

public class Person {  private String name;  private Integer age;  public Person(String name, Integer age) {    super();    this.name = name;    this.age = age;  }  public Person() {    super();  }  public String getName() {    return name;  }   public void setName(String name) {    this.name = name;  }  public Integer getAge() {    return age;  }  public void setAge(Integer age) {    this.age = age;  }  @Override  public String toString() {    return "Person [name=" + name + ", age=" + age + "]";  }  }

新建beans.xml文件

<bean id="person" class="com.lvbl.beans.Person">    <property name="age" value="23"></property>    <property name="name" value="lvbl"></property></bean>

测试代码为:

public class MainTest {   public static void main(String[] args) {    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");    Person bean = (Person) applicationContext.getBean("person");    System.out.println(bean);     }}

测试完成:输出如图

第一种方法完结,没有问题,现在我们进入主题,使用注解配置

新建配置类:MainConfig.class

@Configuration  //告诉Spring这是一个配置类public class MainConfig {  /**   * 使用配置类替换xml文件注入时,返回类型即是方法的返回类型,id默认是方法名   * Bean注解后跟着的别名即是id名,不取默认的方法名   * @return   */  @Bean("person")  public Person superMan() {    return new Person("demo", 2);  }}

注意:@Bean注解效果跟xml文件的bean标签效果相同,如果不指定,则返回类型为方法的返回类型,而id呢?默认值是方法名,若指定,则@Bean后面跟别名

测试代码:

ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);    //用返回类型获取bean    Person bean = applicationContext.getBean(Person.class);    System.out.println("使用返回类型获取" + bean);    //使用id获取    Person bean1 = (Person) applicationContext.getBean("person");    System.out.println("使用id名获取" + bean1);      String[] namesForType = applicationContext.getBeanNamesForType(Person.class);    for (String name : namesForType) {      System.out.println("id:" + name);    }

输出结果:

那么,在xml文件中的bean标签下可以配置包扫描,用注解当然也可以啊,

@ComponentScan注解就是用来解决包扫描问题的

@Configuration  //告诉Spring这是一个配置类@ComponentScan(value="com.lvbl",includeFilters = {    @Filter(type=FilterType.ANNOTATION,classes={Controller.class})},useDefaultFilters = false)

将配置文件改成以上模样

@ComponentScan(value="com.lvbl"):扫描该包下所有的类,在JDK1.8的时候还可以写多个@ComponentScan

includeFilters = Filter[] :指定扫描的时候只需要包含哪些组件

useDefaultFilters = false:关闭默认开关

类似的规则还有:

excludeFilters = Filter[] :指定扫描的时候按照什么规则排除那些组件FilterType.ANNOTATION:按照注解FilterType.ASSIGNABLE_TYPE:按照给定的类型;FilterType.ASPECTJ:使用ASPECTJ表达式FilterType.REGEX:使用正则指定FilterType.CUSTOM:使用自定义规则

Spring默认创建的bean都为单实例,无论从容器获取多少次都相等,使用@Scope("prototype")注解可配置为多例,有时候面试可能会被问到容器创建与bean创建的先后顺序,如下

单实例的情况下:IOC容器在启动的时候会调用方法创建对象放入容器中,之后的每次获取都是从容器中获取;

多实例的情况下:当IOC容器创建时并不会去调用方法创建对象,而是在调用对象时才会调用方法创建,并且每次调用都会执行一遍

由此还可以引出懒加载的概念,懒加载针对的是单实例的情况,使用该注解后,IOC容器初始化后并不会创建bean,而是在调用的时候才创建,这是细节,一定得记住

还有一个自定义规则的注解:@Conditional //按条件创建对象

使用场景如:根据不同的操作系统创建不同的对象

新建LinuxCondition.class,必须实现Condition父类

public class LinuxCondition implements Condition {  /**获取我的电脑操作系统的信息   * ConditionContext:判断条件能使用的上下文(环境)   * AnnotatedTypeMetadata:注释信息   */  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {    // TODO是否linux系统    //获取当前环境信息    Environment environment = context.getEnvironment();      String property = environment.getProperty("os.name");    if(property.contains("linux")){      return true;    }    return false;  }}

新建WindowsCondition.class

public class WindowsCondition implements Condition{  /**   * ConditionContext:判断条件能使用的上下文(环境)   * AnnotatedTypeMetadata:注释信息   */  @Override  public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {    // TODO是否linux系统    //获取当前环境信息    Environment environment = context.getEnvironment();      String property = environment.getProperty("os.name");    if(property.contains("Windows")){      return true;    }    return false;  }}

修改配置类,在@Bean注解上加上@Configuration

public class MainConfig2 {  @Bean("person")  public Person superMan() {    return new Person("person", 1);  }  @Conditional(LinuxCondition.class)  @Bean("linux")  public Person zhangsang() {    return new Person("linux", 1);  }  @Conditional(WindowsCondition.class)  @Bean("windows")  public Person lisi() {    return new Person("Windows", 1);  }}

测试代码和测试结果如图:

很明显,由于我的操作系统为Windows7,所以Linux的对象并未创建

提示:该注解还可以放在类上,只是作用域不用,如果放在类上,则该类所以的bean只有在符合条件时才会被创建

快速注入:@Import,该注解可以快速注入,这种注入方式的id为全类名,在配置类上加上@Import(Book.class),当然,提前新建Book类,测试结果如图

测试代码链接:https://pan.baidu.com/s/1P9n8p3lfB8yPsLNZ_5jyDw

提取码:kdla

————很感谢你看到这里,如果你也喜欢,可以点击分享哦——————

这是我的微信公众号,里面有三千多G的学习资料,从软件到实战项目,剑指Offer面试题集都分类打包好了,扫码关注就能无套路免费领取哦!

 

posted @ 2020-02-24 22:20  za_za_a  阅读(217)  评论(0)    收藏  举报