你有对象吗?

简介: 你有对象吗?

作为一个秃头的开发者,在对方怼不过的时候,经常会被问到一个发自灵魂的拷问你有对象吗?

不但有,哥们有好几个!甚至还有个叫春的管家


在开发过程中让spring管理对象确实是很常见的,也非常方便,有哪些方式呢,我总结了以下几种,咱们具体说下

总览

先讲一个比较骚的大杀器@Import

它主要是做拓展的时候使用,导入一个配置文件,经常搭配自定义注解使用

1. @Import直接导入类

代码示例如下:

public class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
/**
* 直接使用@Import导入person类,然后尝试从applicationContext中取,成功拿到
**/
@Import(Person.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}

使用@Import导入了一个类,会自动把类放置到IOC容器中。


2. @Import 配合 ImportSelector使用

这种方式,平常用的比较少,不过在@Import注解的源码中,说的已经很清楚了,感兴趣的可以看下,我们实现一个ImportSelector的接口,然后实现其中的方法,进行导入。

@Import(MyImportSelector.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class MyImportSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.springboot.pojo.Person"};
    }
}


3. @Import 配合 ImportBeanDefinitionRegistrar使用

这种方式也不太常用,需要我们自己实现 ImportBeanDefinitionRegistrar 接口中的方法,具体代码如下

@Import(MyImportBeanDefinitionRegistrar.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        // 构建一个beanDefinition, 关于beanDefinition我后续会介绍,可以简单理解为bean的定义.
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
        // 将beanDefinition注册到Ioc容器中.
        registry.registerBeanDefinition("person", beanDefinition);
    }
}

上述实现其实和Import的第二种方式差不多,都需要去实现接口,然后进行导入就行。


4. @Import 配合 DeferredImportSelector使用

这种方式和第二种差别不大。只是Spring的处理方式不一样,使用方式如下:

@Import(MyDeferredImportSelector.class)
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class MyDeferredImportSelector implements DeferredImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        // 也是直接将Person的全限定名放进去
        return new String[]{Person.class.getName()};
    }
}



再说两种常见的

@Componet 配合@ComponentScan

这种是用组件的方式来实,这种也比较常见,在配置类上的@ComponentScan可以当做是一个扫描器,扫描带有@Componet注解的bean,然后加至容器中。 具体代码如下:

@Component
public class Person {
    private String name;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                '}';
    }
}
@ComponentScan(basePackages = "com.springboot.initbean.*")
public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}


@Configuration 配合@Bean

首先来说下最常用的,先用@Configuration来声明一个配置类,然后使用 @Bean 注解,这类似于SpringMVC中的配置,最常用,我就不多讲了,就是如下操作:

@Configuration
public class MyConfiguration {
    @Bean
    public Person person() {
        Person person = new Person();
        person.setName("spring");
        return person;
    }
}


最后说两种不太常用的:

1.使用FactoryBean接口

FactoryBean接口和BeanFactory可能有的新手会经常搞混,新手面试官也爱问这个问题,实际上他们的功能是不太一样的,区别的话其实从名字上就可以看出来,就比如,FactoryBean后缀为bean,所以它就是个bean,而BeanFactory后缀是Factory,它是IOC容器的顶级接口。

代码示例:

@Configuration
public class Demo1 {
    @Bean
    public PersonFactoryBean personFactoryBean() {
        return new PersonFactoryBean();
    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(Demo1.class);
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class PersonFactoryBean implements FactoryBean<Person> {
    /**
     *  直接new出来Person进行返回.
     */
    @Override
    public Person getObject() throws Exception {
        return new Person();
    }
    /**
     *  指定返回bean的类型.
     */
    @Override
    public Class<?> getObjectType() {
        return Person.class;
    }
}

上述代码,我使用@Configuration + @Bean的方式将 PersonFactoryBean 加入到容器中,这里注意,我的操作是,并没有向容器中注入 Person, 而是注入的 PersonFactoryBean 然后从容器中直接拿的Person。

2.使用 BeanDefinitionRegistryPostProcessor

这种方式是利用了BeanDefinitionRegistry,因为Spring启动时会执行BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry 方法,它们的作用是可以调整IOC容器中的beanDefinition,从而影响后面Bean的初始化,从而影响功能。

代码示例如下:

public class Demo1 {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        MyBeanDefinitionRegistryPostProcessor beanDefinitionRegistryPostProcessor = new MyBeanDefinitionRegistryPostProcessor();
        applicationContext.addBeanFactoryPostProcessor(beanDefinitionRegistryPostProcessor);
        applicationContext.refresh();
        Person bean = applicationContext.getBean(Person.class);
        System.out.println(bean);
    }
}
class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Person.class).getBeanDefinition();
        registry.registerBeanDefinition("person", beanDefinition);
    }
    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
    }
}

们可以手动向beanDefinitionRegistry中注册了person的BeanDefinition。然后成功将person加入到applicationContext中。

相关文章
|
2月前
|
C++
C++中的对象
C++中的对象
30 2
|
2月前
|
测试技术 索引
v-for 与对象
v-for 与对象
|
9月前
|
前端开发
67 # 对象的处理
67 # 对象的处理
22 0
|
10月前
|
存储 程序员 编译器
C++都有对象了,你还没有吗?
C++都有对象了,你还没有吗?
58 0
|
12月前
|
存储 JSON Java
谈“对象“
谈“对象“
|
存储 编译器 C语言
我现在必须new一个对象!!!
C++内存管理,手动开辟空间,我现在必须new一个对象!!!
66 0
我现在必须new一个对象!!!
|
算法 Java
对象的比较
本篇文章是对Java中一些常见的比较的总结,在涉及到比较方面,有元素的比较与对象的比较,下边博主来带领大家一起了解这些比较方式。
82 0