srping boot:IOC

準(zhǔn)備

java版本:java8
spring boot版本:2.1.10

構(gòu)建spring boot項(xiàng)目,添加lombok依賴

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>

1、組件注冊(cè)

a. @Configuration和@Bean給容器中注冊(cè)組件

構(gòu)建實(shí)體類Person.class

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Person {

    private String name;

    private Integer age;
}

注入組件

@Configuration // 告訴spring這是一個(gè)配置類
public class MainConfig {

    /**
     *給spring容器注冊(cè)一個(gè)bean,默認(rèn)bean的id為方法名稱,即“mike”
     */
    @Bean
    public Person mike() {
        return new Person("麥克", 21);
    }

    @Bean
    public Person jack() {
        return new Person("杰克", 13);
    }
}

測(cè)試

    @Test
    public void PersonBeanTest() {
        // 獲取MainConfig.class的上下文環(huán)境
        ApplicationContext context =
                new AnnotationConfigApplicationContext(MainConfig.class);

//        若MainConfig.class中存在多個(gè)Person的bean會(huì)拋出異常
//        Person mike = context.getBean(Person.class); // error
//        System.out.println(mike);

        Person mike = context.getBean("mike", Person.class); // 根據(jù)id獲取bean
        System.out.println(mike); // Person(name=麥克, age=21)

        String[] beanNames = context.getBeanNamesForType(Person.class); // 獲取bean名稱列表
        System.out.println(Arrays.toString(beanNames)); // [mike, jack]
    }

b. @ComponentScan自動(dòng)掃描組件

//value指定掃描包的路徑
@ComponentScan(value = "com.smallbear.springcoredemo.config")
public class ScanConfig {
}

測(cè)試

    @Test
    public void componentScanTest() {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(ScanConfig.class);
        String[] beanNames = context.getBeanDefinitionNames(); // 獲取掃描到的組件名稱
        for (String s : beanNames) {
            System.out.println(s); // scanConfig、mainConfig、mike、jack,還有幾個(gè)spring自身的組件
        }
    }

c. @Scope設(shè)置組件作用域

MainConfig.class中添加組件

    //默認(rèn)為單實(shí)例(singleton),程序啟動(dòng)的時(shí)候便會(huì)調(diào)用該方法將生成的對(duì)象實(shí)例注入到ioc容器中
    @Scope
    @Bean
    public Person tom() {
        System.out.println("注冊(cè)組件tom");
        return new Person("湯姆", 41);
    }

    //多實(shí)例模式,ioc容器啟動(dòng)時(shí)并不會(huì)立即創(chuàng)建對(duì)象,每次獲取的時(shí)候會(huì)調(diào)用該方法創(chuàng)建一個(gè)對(duì)象
    @Scope("prototype")
    @Bean
    public Person snow() {
        System.out.println("注冊(cè)組件snow");
        return new Person("雪諾", 31);
    }

測(cè)試

    @Test
    public void scopeTest() {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(MainConfig.class);

        System.out.println("獲取組件...");
        Person tom1 = context.getBean("tom", Person.class);
        Person tom2 = context.getBean("tom", Person.class);
        System.out.println("tom1==tom2: " + (tom1 == tom2));
        Person snow1 = context.getBean("snow", Person.class);
        Person snow2 = context.getBean("snow", Person.class);
        System.out.println("snow1==snow2: " + (snow1 == snow2));
    }
/*
print result:
注冊(cè)組件tom
獲取組件...
tom1==tom2: true
注冊(cè)組件snow
注冊(cè)組件snow
snow1==snow2: false
*/

d. @Import快速的給容器導(dǎo)入一個(gè)組件

創(chuàng)建一個(gè)實(shí)體類

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Color {
    private String name;
}

MainConfig.java類上添加注解@Import({Color.class})便成功將Color.class注冊(cè)到容器中,組件名稱為com.smallbear.springcoredemo.entity.Color。

e. @Conditional按照條件注冊(cè)bean

實(shí)現(xiàn)Condition接口

public class WindowsCondition implements Condition {

    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
        Environment environment = context.getEnvironment();
        String property = environment.getProperty("os.name");
        System.out.println(property); // Windows 7
        return property != null && property.contains("Windows");
    }
}

MainConfig.class注入bean

    /**
     *若操作系統(tǒng)是Windows系統(tǒng),則注入bill組件
     */
    @Conditional(WindowsCondition.class)
    @Bean
    public Person bill() {
        return new Person("比爾蓋茨", 65);
    }

f. 使用FactoryBean注冊(cè)組件

public class ColorFactoryBean implements FactoryBean<Color> {

    @Override
    public Color getObject() throws Exception {
        return new Color("red");
    }

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

    /**
     * 是否是單實(shí)例, FactoryBean接口的默認(rèn)返回true
     */
    @Override
    public boolean isSingleton() {
        return true;
    }
}

MainConfig.class中注入bean

    @Bean
    public ColorFactoryBean colorFactoryBean() {
        return new ColorFactoryBean();
    }

測(cè)試

    @Test
    public void factoryBeanTest() {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(MainConfig.class);

        //容器中注入的是colorFactoryBean組件,但獲取的時(shí)候返回的是color對(duì)象
        Color color = context.getBean("colorFactoryBean", Color.class);
        System.out.println(color.getName()); // red
    }

g. 小結(jié)

容器中常用的注冊(cè)bean的方法
1、組件標(biāo)注注解(@Controller, @Service, @Component, @Repository等)
2、@Bean
3、@Import
4、使用FactoryBean工廠

2、bean的生命周期

a. @Bean指定初始化和銷毀方法

@Data
public class Car {

    private String name;

    private BigDecimal price;

    public Car() {
        System.out.println("car constructor...");
    }

    public Car(String name, BigDecimal price) {
        this.name = name;
        this.price = price;
        System.out.println(this.name + " constructor...");
    }

    public void init() {
        System.out.println(name + " init...");
    }

    public void destroy() {
        System.out.println(name + " destroy...");
    }
}

/**
 * bean的生命周期(由容器來(lái)管理):創(chuàng)建---初始化---銷毀
 * 可以自定義初始化和銷毀方法
*/
@Configuration
public class MainConfigOfLifeCycle {

    /**
     *指定容器的初始化和銷毀方法
     * 1、單實(shí)例
     * 初始化:對(duì)象創(chuàng)建完成時(shí)調(diào)用
     * 銷毀:容器關(guān)閉時(shí)調(diào)用
     */
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car benz() {
        return new Car("奔馳", BigDecimal.valueOf(200000));
    }

    /**
     * 2、多實(shí)例
     * 初始化 獲取bean時(shí)觸發(fā)
     * 銷毀 不會(huì)主動(dòng)銷毀
     */
    @Scope("prototype")
    @Bean(initMethod = "init", destroyMethod = "destroy")
    public Car BYD() {
        return new Car("比亞迪", BigDecimal.valueOf(12000));
    }
}

測(cè)試

    @Test
    public void BenzTest() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(MainConfigOfLifeCycle.class);
        System.out.println("容器啟動(dòng)完成...");
        Car BYD = context.getBean("BYD", Car.class);
        context.close();
    }
/*
奔馳 constructor...
奔馳 init...
容器啟動(dòng)完成...
比亞迪 constructor...
比亞迪 init...
奔馳 destroy...
*/

b. InitializingBean和DisposableBean

通過(guò)InitializingBeanDisposableBean接口實(shí)現(xiàn)bean初始化和銷毀方法

public class Cat implements DisposableBean, InitializingBean {


    @Override
    public void destroy() throws Exception {
        System.out.println("cat destroy...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("cat init...");
    }
}

c. @PostConstruct和@PreDestroy

通過(guò)@PostConstruct@PreDestroy注解實(shí)現(xiàn)bean初始化和銷毀方法

public class Dog {
    
    @PostConstruct
    public void init() {
        System.out.println("cat init...");
    }
    
    @PreDestroy
    public void destroy() {
        System.out.println("dog destroy...");
    }
}

d. BeanPostProcessor

BeanPostProcessorBean初始化后置處理器

/**
 * Bean初始化后置處理器
 */
@Component
@ComponentScan("com.smallbear.springcoredemo")
public class MyBeanPostProcessor implements BeanPostProcessor {

    /**
     *初始化之前執(zhí)行
     */
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "->before init...");
        return bean;
    }

    /**
     * 初始化之后執(zhí)行
     */
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println(beanName + "->after init...");
        return bean;
    }
}

測(cè)試

    @Test
    public void beanPostProcessorTest() {
        AnnotationConfigApplicationContext context =
                new AnnotationConfigApplicationContext(MyBeanPostProcessor.class);
        Car BYD = context.getBean("BYD", Car.class);
        context.close();
    }
/*
print result部分內(nèi)容:
比亞迪 constructor...
BYD->before init...
比亞迪 init...
BYD->after init..
*/

3. 自動(dòng)裝配

構(gòu)建新的spring boot項(xiàng)目

a. @Autowired和@Qualifier

@Autowired:自動(dòng)注入:
1、優(yōu)先按照類型去容器中查找對(duì)應(yīng)的組件
2、如果有過(guò)個(gè)相同類型的組件,再將屬性名作為id去容器中尋找
@Qualifier:指定需要裝配的組件的id

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Pet {
   private String name;
}
@Configuration
@ComponentScan("com.smallbear.springcoredemo2")
public class MainConfigOfAutoWired {

    //注冊(cè)name為duck、cat、mouse的組件,
    // 由于米奇和杰瑞組件的名稱相同,杰瑞組件沒(méi)有注冊(cè)到容器中

    @Bean
    public Pet duck() {
        return new Pet("唐老鴨");
    }

    @Bean("cat")
    public Pet cat() {
        return new Pet("湯姆");
    }

    @Bean
    public Pet mouse() {
        return new Pet("米奇");
    }

    @Primary
    @Bean("mouse")
    public Pet mouse2() {
        return new Pet("杰瑞");
    }
}
@Service
public class PetService {

    @Autowired
    private Pet duck; // 注入唐老鴨

    @Qualifier("cat") // 指定需要裝配的組件的id
    @Autowired
    private Pet pet; // 此處注入id為cat的組件(湯姆)

    @Autowired
    private Pet mouse; // 注入米奇

    public void printDuck() {
        System.out.println(duck.getName());
    }

    public void printCat() {
        System.out.println(pet.getName());
    }

    public void printMouse() {
        System.out.println(mouse.getName());
    }
}
    @Test
    public void test01() {
        ApplicationContext context =
                new AnnotationConfigApplicationContext(MainConfigOfAutoWired.class);
        PetService petService = context.getBean("petService", PetService.class);

        String[] petNames = context.getBeanNamesForType(Pet.class);
        System.out.println(Arrays.toString(petNames)); // [duck, cat, mouse]
        petService.printDuck(); // 唐老鴨
        petService.printCat(); // 湯姆
        petService.printMouse(); // 米奇
    }

b. 支持@Resource(java規(guī)范的注解)

c. 方法、構(gòu)造器位置的自動(dòng)裝配

@Component
public class MyPet {
    
    private Pet cat;
    
    private Pet mouse;
    
    @Autowired // 注入湯姆
    public MyPet(Pet cat) {
        this.cat = cat;
    }
    
    @Autowired // 注入米奇
    private void setMouse(Pet mouse) {
        this.mouse = mouse;
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 銀行賬戶大家都不陌生,通過(guò)不斷的存錢,增加儲(chǔ)蓄余額,在需要的時(shí)候可以提取。情感也是一樣,如果想長(zhǎng)久維持人和人之間的...
    慢游小魚(yú)閱讀 532評(píng)論 1 4
  • 左手尿不濕,右手腳趾頭,嘴里叼了一小本撕爛的書(shū),僅剩的一只腳不停的在我的臉上又蹬又踹!這就是我今天早上醒來(lái)看見(jiàn)小寶...
    大陳_8fcc閱讀 136評(píng)論 0 0
  • 我愚蠢的以為自己很好,卻不曾知道很多很多人比自己好卻不會(huì)高傲。 跟一個(gè)同學(xué)聊天,知道他同樣也擁有著一個(gè)作家夢(mèng)。...
    皮兮歪閱讀 367評(píng)論 0 0
  • 今天在做小程序開(kāi)發(fā)時(shí)遇到幾個(gè)小問(wèn)題,故此記錄,以便以后查閱 注冊(cè)賬號(hào),暫時(shí)了解到的有兩種方式: 1.直接 進(jìn)入ht...
    愿此生安好閱讀 392評(píng)論 0 0

友情鏈接更多精彩內(nèi)容