spring注解開發:容器中注冊組件方式


1、包掃描+組件標注注解


使用到的注解如下,主要針對自己寫的類

  • @Controller
  • @Service
  • @Repository
  • @Component
  • @ComponentScan

參考 spring注解開發:ComponentScan組件掃描

2、使用bean注解


主要使用場景:導入第三方包里面的組件,使用到的注解:

  • @Bean
參考:spring注解開發:Configuration&Bean

3、使用@Import注解


  • 使用方式:@Import(要導入到容器中的組件);容器中就會自動注冊這個組件
  • bean的id默認是全類名
  • 示例:@Import(value = {Person.class})

實戰

1、新建一個maven工程,添加如下依賴

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.0.5.RELEASE</version>
</dependency>

2、新建一個實體 Person

package com.yefengyu.annotation.bean;

public class Person
{
    private String name;

    private Integer age;

    public Person()
    {
    }

    public Person(String name, Integer age)
    {
        this.name = name;
        this.age = age;
    }

    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 +
               '}';
    }
}

3、新建一個配置類(重點

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import(Person.class)
public class MainConfig
{
}

4、測試代碼

public static void main(String[] args)
{
    ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
    String[] names = ctx.getBeanDefinitionNames();
    for (String name : names)
    {
        System.out.println(name);
    }
    Person person1= (Person)ctx.getBean(Person.class);
    //bean的id默認是全類名
     Person person2= (Person)ctx.getBean("com.yefengyu.annotation.bean.Person");
}

4、使用ImportSelector


ImportSelector和Import一起使用:首先編寫一個類實現ImportSelector接口MyImportSelector,然后將MyImportSelector添加到Import中,那么MyImportSelector自定義邏輯返回需要導入的組件就會被加入到容器中。

利用上面第三節的代碼,我們重新添加一個類,這個類什么都沒有,現在我們嘗試着使用ImportSelector方式將其注冊到容器中。

package com.yefengyu.annotation.bean;

public class Car
{
}

1、編寫MyImportSelector實現ImportSelector接口,重寫selectImports方法,返回的數組中每個字符串就是要導入到容器的組件的全類名。

package com.yefengyu.annotation;

import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

//自定義邏輯返回需要導入的組件
public class MyImportSelector implements ImportSelector
{
    //返回值就是要導入到容器的組件的全類名
     @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata)
    {
        return new String[]{"com.yefengyu.annotation.bean.Car"};
    }
}

2、修改MainConfig配置類,使用Import注解加入MyImportSelector類,注意下面紅色部分。

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class})
public class MainConfig
{
}

3、測試,同樣使用上面的測試代碼,可以看出打印結果為:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car

4、針對於public String[] selectImports(AnnotationMetadata annotationMetadata)方法中的參數AnnotationMetadata有很多信息可以幫助篩選要注冊的組件。

image

5、使用ImportBeanDefinitionRegistrar


和使用ImportSelector方式一樣,定義一個類實現ImportBeanDefinitionRegistrar接口,重寫其中的方法,手動注冊組件。

1、定一個類,作為要注冊的組件

package com.yefengyu.annotation.bean;

public class Alarm
{
}

2、實現ImportBeanDefinitionRegistrar接口,手動注冊組件

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Alarm;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;


public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar
{
    @Override
    public void registerBeanDefinitions(AnnotationMetadata annotationMetadata,
                                        BeanDefinitionRegistry beanDefinitionRegistry)
    {
        beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));
    }
}

beanDefinitionRegistry.registerBeanDefinition("alarm",new RootBeanDefinition(Alarm.class));

第一個參數是組件名稱。

第二個參數是要注冊的組件的類型的定義。

AnnotationMetadata 和上一節類似。BeanDefinitionRegistry 的功能很多:

image

3、修改MainConfig配置類,使用Import注解加入MyImportBeanDefinitionRegistrar類,注意下面紅色部分。

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
}

4、測試,同樣使用上面的測試代碼,可以看出打印結果為:

org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalRequiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
alarm

6、使用FactoryBean


1、首先創建一個待加入到容器的組件

package com.yefengyu.annotation.bean;

public class Event
{
}

2、創建一個Spring定義的FactoryBean

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Event;
import org.springframework.beans.factory.FactoryBean;


//創建一個Spring定義的FactoryBean
public class EventFactoryBean implements FactoryBean<Event>
{
    //返回一個Event對象,這個對象會添加到容器中
    @Override
    public Event getObject()
        throws Exception
    {
        return new Event();
    }

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

    //是單例?
    //true:這個bean是單實例,在容器中保存一份
    //false:多實例,每次獲取都會創建一個新的bean;
    @Override
    public boolean isSingleton()
    {
        return true;
    }
}

3、修改配置類,注意下面bean注解下面的代碼

package com.yefengyu.annotation.config;

import com.yefengyu.annotation.EventFactoryBean;
import com.yefengyu.annotation.MyImportBeanDefinitionRegistrar;
import com.yefengyu.annotation.MyImportSelector;
import com.yefengyu.annotation.bean.Person;
import org.springframework.context.annotation.*;


@Configuration
@Import({Person.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
public class MainConfig
{
    @Bean
    public EventFactoryBean eventFactoryBean()
    {
        return new EventFactoryBean();
    }
}

4、修改測試代碼如下:

package com.yefengyu.annotation;

import com.yefengyu.annotation.bean.Person;
import com.yefengyu.annotation.config.MainConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;


public class Main
{
    public static void main(String[] args)
    {
        ApplicationContext ctx= new AnnotationConfigApplicationContext(MainConfig.class);
        String[] names = ctx.getBeanDefinitionNames();
        for (String name : names)
        {
            System.out.println(name);
        }
        //測試EventFactoryBean
        Object eventFactoryBean = ctx.getBean("eventFactoryBean");
        System.out.println("bean 的類型為:" + eventFactoryBean.getClass());

        Object factoryBean = ctx.getBean("&eventFactoryBean");
        System.out.println("bean 的類型為:" + factoryBean.getClass());
    }
}

5、結果如下:

mainConfig
com.yefengyu.annotation.bean.Person
com.yefengyu.annotation.bean.Car
eventFactoryBean
alarm
bean 的類型為:class com.yefengyu.annotation.bean.Event bean 的類型為:class com.yefengyu.annotation.EventFactoryBean

總結:

  • 默認獲取到的是工廠bean調用getObject創建的對象

    ctx.getBean("eventFactoryBean");

  • 要獲取工廠Bean本身,我們需要給id前面加一個&

    ctx.getBean("&eventFactoryBean");

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM