spring ioc 初探

我们学习spring 的第一天就知道 spring 主要的两大特性就是 IOC 、AOP

基于平时的开发工作我们也主要是写一写业务代码,很难接触到借助于spring 封装一些中间件,这也导致我们对spring的理解不够深入,spring可谓是对软件设计的原则和设计模式应该的出神入化了,面向对象的思想再它的整个架构中都可以看到。今天我就 IOC 这点这个谈一下自己的理解

IOC The Inversion of Control (IoC) 控制反转,官方的解析就是 对象的创建和依赖管理由开发人员交给spring这个就字面意思理解确实是很容易懂。但是一句话就能把IOC 说清楚了吗?思与深而行与浅 我觉的这才是IOC 的亮点。

我对IOC的理解,IOC 确实是控制反转的思想,但是spring是怎样去实现的呢。目前我觉的有这几种

1、通过原始的xml实现

xml应该算最老的方式向spring中注入bean 了

spring.xml


<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.sunjin.vip.bean.User">
        <property name="id" value="1"/>
        <property name="name" value="sunjin"/>
    bean>
beans>
  public static void main(String[] args) {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-application.xml");
        User user = applicationContext.getBean(User.class);
        System.out.println(user);
    }

当前解析配置文件的过程

AbstractApplicationContext#refresh()

->obtainFreshBeanFactory() 这个方法去解析配置

2、通过 @Component 和它的派生注解 @Controller @Service @Repository 加上注解扫描 @ComponentScan

@ComponentScan("com.sunjin.vip.controller")
public class CommonConfiguration {
}
@Controller
public class SayHelloController {
}

public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(CommonConfiguration.class);
        SayHelloController sayHelloController = annotationConfigApplicationContext.getBean(SayHelloController.class);
        System.out.println(sayHelloController);
    }

这这种方式也可以向spring容器注册bean 当然@ComponentScan生效的机制就是在ConfigurationClassPostProcessor中

3、通过@Bean向spring注册一个bean

public class ConfigurationRegisterBean {

    @Bean("user1")
    public User user(){
        User user = new User();
        user.setId("1");
        user.setName("sunjin");
        return user;
    }

    @Bean("user2")
    public User user2(){
        User user = new User();
        user.setId("2");
        user.setName("sj");
        return user;
    }
}

public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ConfigurationRegisterBean.class);
        User user = (User) annotationConfigApplicationContext.getBean("user2");
        System.out.println(user.getName());
    }

这种实现的方式是ConfigurationClassBeanDefinitionReader#loadBeanDefinitions(configClasses)

->loadBeanDefinitionsForBeanMethod(beanMethod)

这种方式去加载的bean

4、通过@Configuration 想spring 注册bean

@Configuration
public class CommonConfiguration {
}
@ComponentScan(basePackageClasses = CommonConfiguration.class)
public class ConfigurationRegisterBean {
}
public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(ConfigurationRegisterBean.class);
        CommonConfiguration commonConfiguration = annotationConfigApplicationContext.getBean(CommonConfiguration.class);
        System.out.println(commonConfiguration);
    }

5、通过@Import 和 @Configuration | @Import 和 ImportSelector | @Import 和 ImportBeanDefinitionRegistrar

//@Import 和  ImportSelector
@Import(ImportSelectorUser.class)
public class ImportSelectorUserConfig {
}
public class ImportSelectorUser implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {

        return new String[]{User.class.getName()};
    }
}
//@Import 和 ImportBeanDefinitionRegistrar
@Import(ImportBeanDefinitionRegisterParcel.class)
public class ImportBeanDefinitionRegisterParcelConfig {
}

public class ImportBeanDefinitionRegisterParcel implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        RootBeanDefinition beanDefinition = new RootBeanDefinition();
        beanDefinition.setBeanClass(Parcel.class);
        registry.registerBeanDefinition("parcel", beanDefinition);

    }
}

6、通过 Factorybean注册特定的bean

public class FactoryBeanParcel implements FactoryBean<Parcel> {
    @Override
    public Parcel getObject() throws Exception {
        return new Parcel();
    }

    @Override
    public Class<?> getObjectType() {
        return Parcel.class;
    }

    @Override
    public boolean isSingleton() {
        return false;
    }
}
@Configuration//无实际意义
public class FactoryBeanParcelConfig{

    @Bean
    public FactoryBeanParcel factoryBeanParcel(){
        return new FactoryBeanParcel();
    }
}
 public static void main(String[] args) throws Exception {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(FactoryBeanParcelConfig.class);
        FactoryBeanParcel bean = annotationConfigApplicationContext.getBean(FactoryBeanParcel.class);
        System.out.println(bean.getObject());
    }

这种方式的实现 利用了factoryBean的特性了,spring中的bean分两种一种普通的bean 一种是 factorybean 为了复杂对象的创建 spring 提供了factorybean

7、通过@Conditional按条件装配bean

这种方式的注册bean我这就不在举例了 可以参考 @Profile

spring 的这个注解实现就是按照 Conditional

通过上面几种方式的说明不知道你对spring IOC的实现方式有没有自己的想法目前这期没有涉及到DI\DL 的部分下期开始会说明spring 中DI\DL的实现方式。

结束语 :spring 应该是目前使用最广的 java框架了 spring 的生态和它的编程思想赢响了一代又一代程序猿。

你可能感兴趣的:(spring,spring,4.3.25源码分析)