美文网首页Java
Spring (IOC、DI)

Spring (IOC、DI)

作者: TZX_0710 | 来源:发表于2019-09-16 17:13 被阅读0次

IOC容器是一个管理Bean的容器,它要求所有的Bean都需要实现接口
BeanFactory是一个顶级的容器接口

BeanFactory.class 源码


public interface BeanFactory {
    String FACTORY_BEAN_PREFIX = "&";
      //获取Bean
    Object getBean(String var1) throws BeansException;

    <T> T getBean(String var1, Class<T> var2) throws BeansException;

    Object getBean(String var1, Object... var2) throws BeansException;

    <T> T getBean(Class<T> var1) throws BeansException;

    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;

     //获取Bean的提供者
    <T> ObjectProvider<T> getBeanProvider(Class<T> var1);

    <T> ObjectProvider<T> getBeanProvider(ResolvableType var1);
  
   //是否包含该Bean
    boolean containsBean(String var1);
  //是否是单例
    boolean isSingleton(String var1) throws NoSuchBeanDefinitionException;
   //是否是原型
    boolean isPrototype(String var1) throws NoSuchBeanDefinitionException;
   //是否类型匹配
    boolean isTypeMatch(String var1, ResolvableType var2) throws NoSuchBeanDefinitionException;

    boolean isTypeMatch(String var1, Class<?> var2) throws NoSuchBeanDefinitionException;

    //获取类型
    @Nullable
    Class<?> getType(String var1) throws NoSuchBeanDefinitionException;
   //获取别名
    String[] getAliases(String var1);
}

从上面可以结合中文注释可以看出 BeanFactory中提供的方法的一些作用

  • isSingleton 判断这个Bean是否是单例的,默认情况下容器中的Bean都是单例的
  • isPrototype 和isSingleton的相反,如果返回true每次从容器当中获取一个Bean都是重新创建
  • BeanFactory提供的方法是一些常用的对Bean获取方法,但是工作中可能我们的需求更大所以需要更多。在此之上也提供了一个更高级的注解ApplicationContext 在使用IOC容器的时候,大部分类都实现来自己 ApplicationCOntext接口。

演示框架采用SpringBoot最新版本

@Data
public class Users {

    private Integer id;

    private String userName;

    private String userId;

    public Users(Builder builder) {
        id = builder.id;
        userId = builder.userId;
        userName = builder.userName;
    }

    //Builder构造器模式
    public static class Builder {
        int id;

        String userName;

        String userId;

        public Builder(int id, String userName, String userId) {
            this.id = id;
            this.userName = userName;
            this.userId = userId;
        }

        public Builder id(int id) {
            this.id = id;
            return this;
        }

        public Builder userName(String userName) {
            this.userName = userName;
            return this;
        }

        public Builder userId(String userId) {
            this.userId = userId;
            return this;
        }

        public Users builder() {
            return new Users( this );
        }
    }
}

上面采用构造器模式 原因只是 个人想复习一下 没有其他想表达的意思,望别误入

//表示一个配置文件
@SuppressWarnings("ALL")
@Configuration
public class ApplicationConfig {

    //表示声明一个user的Bean如果没有user那么会直接采用方法名作为这个Bean的名称
    @Bean("user")
    public Users initUser() {
        Users users = new Users.Builder( 1, "zhangsan", "lucy" ).builder();
//        Users users=new Users(  );
//        users.setId( 1 );
//        users.setUserName( "张三" );
//        users.setUserId( "Lucy" );
        return users;
    }
}

测试

public class IocTest {
    //SpringBoot自带日志
    private static Logger logger= LoggerFactory.getLogger( IOContext.class );
    public static void main(String[] args) {
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(
                        ApplicationConfig.class );
        Users bean = applicationContext.getBean( Users.class );

        logger.debug( bean.toString() );
    }
}

14:57:17.223 [main] DEBUG com.fasterxml.jackson.core.io.IOContext - Users(id=1, userName=zhangsan, userId=lucy)

我们可以通过第一种方式加载Bean
还可以通过扫描的方式加载Bean
采用SpringBoot的ComponentScan 扫描 不多BB直接看源码 用法 自行百度

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Documented
@Repeatable(ComponentScans.class)
public @interface ComponentScan {
   //定义扫描的包
    @AliasFor("basePackages")
    String[] value() default {};


    //扫描包路径  默认扫描当前包以及他的子包
    @AliasFor("value")
    String[] basePackages() default {};

    //定义扫描的类
    Class<?>[] basePackageClasses() default {};
      //BeanName生成器
    Class<? extends BeanNameGenerator> nameGenerator() default BeanNameGenerator.class;
    //作用域解析器
    Class<? extends ScopeMetadataResolver> scopeResolver() default AnnotationScopeMetadataResolver.class;
    //作用域代理器
    ScopedProxyMode scopedProxy() default ScopedProxyMode.DEFAULT;
    //资源匹配模式
    String resourcePattern() default "**/*.class";
  //是否启用默认过滤 默认true
    boolean useDefaultFilters() default true;
    //满足条件扫描                不满足的时候不扫描
    ComponentScan.Filter[] includeFilters() default {};
     当不满足条件时间扫描   满足的时候 过滤
    ComponentScan.Filter[] excludeFilters() default {};
     //是否延迟加载 默认为false
    boolean lazyInit() default false;

    @Retention(RetentionPolicy.RUNTIME)
    @Target({})
    public @interface Filter {
        FilterType type() default FilterType.ANNOTATION;

        @AliasFor("classes")
        Class<?>[] value() default {};

        @AliasFor("value")
        Class<?>[] classes() default {};

        String[] pattern() default {};
    }
}
IoC 的三个经典问题
对于 IoC 有三个经典问题:谁控制谁?控制了什么?怎么实现了反转?很多博客里都进行了一个回答,笔者也按照自己的故事模式进行一个回答。
* “谁控制谁?”:IoC / DI 容器控制应用程序
* 控制了什么?:IoC / DI 容器控制对象本身的创建、实例化,以及控制对象之间的依赖关系;
* 开发之中的对象已经全部交由 IoC 容器来管理了,那我们在获取对象的时候,就得由 IoC 容器来给我们提供;
2.3 DI 的三个经典问题
* “谁依赖谁?”:应用程序依赖于 IoC 容器;
* “谁注入了谁?”:IoC 容器把对象注入于应用程序;
* “注入了什么?”:注入应用程序需要的外部资源,比如有依赖关系的对象

相关文章

网友评论

    本文标题:Spring (IOC、DI)

    本文链接:https://www.haomeiwen.com/subject/hwpxuctx.html