IoC
(Inversion of Control) 也被称为 DI
(Dependency Injection)。 对象通过构造参数、工厂参数、set方法等,确定了依赖关系,而 IoC 容器在创建这个对象的时候,将自动为这个对象注入其所需要的依赖。这个过程,就是非常基础的控制反转(IoC)。
beans,就是上面所述由 IoC 容器创建并管理的对象。
IoC 容器 org.springframework.context.ApplicationContxt
接口代表了 Spring 的 IoC 容器,并负责实例化、配置、装配各类 beans。这个过程,依赖于配置元数据(configuration metadata),而配置元数据,就是 XML 文件、Java 注解或者 Java 代码。
1 2 3 4 5 6 @SpringBootApplication public class CustomAutoConfigApplication { public static void main (String[] args) { ConfigurableApplicationContext context = SpringApplication.run(CustomAutoConfigApplication.class, args); } }
Bean 生命周期管理 Bean 的生命周期,大致分为 Bean 定义、Bean初始化、Bean的生存期、Bean的销毁。
Bean 定义
Spring 通过在如 scanBasePackages
设置的扫描路径,找到带有 @Component 类。即,进行资源定位。
解析文件,将定义信息保存起来。
将定义信息发布到 IoC 容器中。注意,这里仍然时 Bean 定义,并没有实例化。
初始化 初始话过程如下所示: 图片来源 《深入浅出Spring Boot 2.x》
整个生命周期
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 @Component public class Apple implements Fruit , BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean ,BeanPostProcessor { private String TGA = Apple.class.getSimpleName() + " " ; @Override public String getFruitName () { return "Apple" ; } @Override public void setBeanFactory (BeanFactory beanFactory) throws BeansException { System.out.println(TGA+"set bean factory......" ); } @Override public void setBeanName (String name) { System.out.println(TGA+"set bean name:" + name); } @Override public void destroy () throws Exception { System.out.println(TGA+"destroy......" ); } @Override public void setApplicationContext (ApplicationContext applicationContext) throws BeansException { System.out.println(TGA+"set Application context..." ); } @Override public void afterPropertiesSet () throws Exception { System.out.println(TGA+"after property set......" ); } @Override public Object postProcessAfterInitialization (Object bean, String beanName) throws BeansException { System.out.println(TGA+"postProcessAfterInitialization,beanName:" + beanName); return BeanPostProcessor.super .postProcessAfterInitialization(bean, beanName); } @Override public Object postProcessBeforeInitialization (Object bean, String beanName) throws BeansException { System.out.println(TGA+"postProcessBeforeInitialization, beanName:" + beanName); return BeanPostProcessor.super .postProcessBeforeInitialization(bean, beanName); } }
常用注解 注解 @Component 表明这个类将被 Spring IoC容器扫描装配,从而建构出一个 Bean。如下所示,“apple”将作为这个 Bean 的名称。默认情况下,IoC 容器会把类名的第一个字母小写,其它不变,作为 Bean 的名称放入到 IoC 容器中。
1 2 3 @Component("apple") public class Apple {}
注解 @ComponentScan 这里加入了 @ComponentScan ,表明它会进行扫描,但是它只会扫描 UserConfig 所在当前包和子包。
1 2 3 4 5 @Configuration @ComponentScan public class UserConfig {}
测试:
1 2 3 4 ApplicationContext context1 = new AnnotationConfigApplicationContext (UserConfig.class) ;User user = context1.getBean(User.class) ;user.setName("test" ); System.out.println(user.getName());
注解 @Configuration @Configuration 代表这是一个 Java 配置文件(相当于一个xml配置文件),Spring 容器将会根据它来装配 Bean(xml 中的 )。即,bei’ta被它标记的类中,通常,其返回值通常会被 IoC 容器管理,被标记为 @Bean。
注解 @Bean 表明方法返回的对象将被 IoC 容器管理。
注解 @Autowired @Autowired 提供这样的规则:首先,它会根据类型找到对应的 Bean,如果对应类型的 Bean 不是唯一的,那么,它会根据期属性名称和 Bean 的名称进行匹配,如果匹配的上,就使用该 Bean,否则,抛出异常(如果 @Autowired 属性 required 为 false,则该值为 null)。
1 2 3 public interface Fruit { String getFruitName () ; }
1 2 3 4 5 6 7 @Component public class Apple implements Fruit { @Override public String getFruitName () { return "Apple" ; } }
1 2 3 4 5 6 7 8 9 10 11 12 13 @Component public class Person { @Autowired private Fruit fruit ; public boolean eatFruit () { if (fruit != null ){ System.out.println("person eat" + fruit.getFruitName()); return true ; }else return false ; } }
@Autowired 可以除了用在属性上,还可以用于方法上,构造参数中。
1 2 3 4 private Fruit fruit ;public Person (@Autowired @Qualifier("apple") Fruit fruit) { this .fruit = fruit ; }
注解 @Primary 注解 @Primary 是一个修改优先注解。根据 @Autowired 的注入规则,我们知道,在进行注入时,容易产生歧义:即,IoC 容器由于找到多个同类型的可注入对象,而不知道要注入哪个。 @Primary 将告诉 IoC 容器,当发现有多个同样类型的 Bean 时,将优先注入使用了 @Primary 注解的 Bean。
1 2 3 4 5 @Component("apple") @Primary public class Apple implements Fruit {}
注解 @Quelifier 对于 @Primary 来说,同样可能会导致歧义,可能有多个同类 Bean 被添加了 @Primary 注解。 在 BeanFactory 中,实际上有一个通过名称和类型找到对象的方法。而使用 @Quelifier 就可以指定 Bean 名称。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Component public class Person { @Autowired @Qualifier("apple") private Fruit fruit ; public boolean eatFruit () { if (fruit != null ){ System.out.println("person eat" + fruit.getFruitName()); return true ; }else return false ; } }
注解 @Service @Service 所标记的类,标识该类提供业务功能。本质上,其实就是 @Component:
1 2 3 4 5 6 7 8 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Service { @AliasFor(annotation = Component.class) String value () default "" ; }
注解 @Controller @Controller 标明其标注的类是处理器,这里更多的其实是标识意义。通常,它会和 @RequestMapping 注解一起使用。@RequestMapping 负责将网络请求的处理映射到 @Controller 标记的对象中的方法。
1 2 3 4 5 6 7 8 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Controller { @AliasFor(annotation = Component.class) String value () default "" ; }
注解 @Repository @Repository 标记该对象扮演数据仓库的角色,负责数据管理。
1 2 3 4 5 6 7 8 @Target({ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) @Documented @Component public @interface Repository { @AliasFor(annotation = Component.class) String value () default "" ; }
参考书籍 《深入浅出Spring Boot 2.x》
参考链接Spring Core Technologies