欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring IOC容器学习,Bean的学习;

程序员文章站 2022-05-23 10:32:29
...

Spring IOC容器学习,Bean的学习;

Bean是什么?

JavaBean是描述Java的软件组件模型,有点类似于Microsoft的COM组件概念。在Java模型中,通过JavaBean可以无限扩充Java程序的功能,通过JavaBean的组合可以快速的生成新的应用程序。对于程序员来说,最好的一点就是JavaBean可以实现代码的重复利用,另外对于程序的易维护性等等也有很重大的意义。

我的理解是对java类的一种包装,对其属性,数值,功能等进行修饰,然后交给IOC实例化,随时使用;

bean规范:

1.所有属性为private(不能是public)
2.提供默认构造方法(必须有一个不带参的构造器)
3.提供getter和sette

传统方式与IOC方式:

传统方式

​ 我们都是通过new的方式获取对象比如 User user1 = new User();

IOC方式(控制反转 Inversion Of Control ):

​ 负责管理bean,发布和获取bean;

​ 通过描述完成bean之间的依赖关系;

其实就是传统方式需要 我们自己买菜,然后根据各种属性啥的自定义这个菜怎么洗,怎么制作;

IOC方式的bean是已经描述好烹饪方式,然后IOC负责把菜烧出来(实例化)直接给我们;

注解方式使用IOC和bean:

方式1

首先定义一个类

package com.nhjia.pojo;

public class Food {
    private String name;
    private String cookingway;

       /* setter and getter 自行添加 */
       /* 无参构造器默认自动包括 */
}

其次定义配置文件:

package com.nhjia.pojo.test;

import com.nhjia.pojo.Food;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
/*表示这是一个配置文件*/
public class Appconfig {
    @Bean(name="food")
    /*该bean的名字,如果没有initFood会被作为名字存入IOC*/
    public Food initFood(){
        Food food = new Food();
        food.setName("猪肉");
        food.setCookingway("红烧肉");
        return food;
    }
}


"食物"买好之后,烹饪方式之后,就直接交给"后厨"IOC做出这道菜

package com.nhjia.pojo.test;

import com.nhjia.pojo.Food;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ctx = new AnnotationConfigApplicationContext(Appconfig.class);
        /*通过AnnotationConfigApplicationContext读取Appconfig里的配置,将配置里的bean装配到IOC中 “获取菜和做菜要求”*/
        Food food = ctx.getBean(Food.class);
        /*获取实例化对象 “取菜”*/
        System.out.println(food.getName());
        System.out.println(food.getCookingway());
    }
}

输出结果:Spring IOC容器学习,Bean的学习;

但是第一种方式,如果有很多种bean,都要写initclass,就会显得很繁琐,所以还有第二种方式,在bean上先进行装配,配置文件只要扫描哪些文件里有bean和bean的装配即可

方式2

package com.nhjia.pojo.FOOD;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("food")
/*@Component表明这个类会被扫描*/
public class Food {
    @Value("猪肉")
    /*@Value表示给这个bean的装配,描述*/
    private String name;
    @Value("红烧肉")
    private String cookingway;

    /* setter and getter */
    }
}

配置文件:

package com.nhjia.pojo.test;

import com.nhjia.pojo.FOOD.Food;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
/*表示这是一个配置文件*/
@ComponentScan
/*@CompontScan表示进行扫描,但是第一种只扫描Appconfig类所在的包和子包package com.nhjia.pojo.test*/
@ComponentScan("com.nhjia.pojo.*")
/*表示在包com.nhjia.pojo和其子包中进行扫描也可以指明com.nhjia.pojo.FOOD*/
@ComponentScan(basePackages = {"com.nhjia.pojo.FOOD"})
/*指定包*/
@ComponentScan(basePackageClasses = {Food.class})
/*也可以指定类*/
public class Appconfig {
}

两种方式下的测试结果相同;

使用到的注解:

 @Configuration
/*表示这是一个配置文件*/
 @Bean(name="food")
 /*该bean的名字,如果没有initFood会被作为名字存入IOC*/


 @Component("food")
/*@Component表明这个类会被扫描*/
 @Value("猪肉")
/*@Value表示给这个bean的装配,描述*/
 @ComponentScan
/*@CompontScan表示进行扫描,但是第一种只扫描Appconfig类所在的包和子包package com.nhjia.pojo.test*/

依赖注入

上述只描述了一种bean类装配到IOC中,但是bean之间有依赖,比如某些厨师精通肉类制作,而某些厨师精于做蔬菜类;这时候猪肉bean就与肉类厨师bean有了依赖

因为厨师都会烹饪所以定义接口

package com.nhjia.pojo.cook;

public interface CookWay {
    public void cook ();
}

定义两种厨师:

package com.nhjia.pojo.cook;

import org.springframework.stereotype.Component;

@Component
public class cook1 implements CookWay{

    @Override
    public void cook() {
        System.out.println("cook1精通于肉类制作");
    }
}
---------------------------------------------------------
package com.nhjia.pojo.cook;

import org.springframework.stereotype.Component;
/*暂时不加 @Component*/
public class cook2 implements CookWay {
    @Override
    public void cook() {
        System.out.println("cook2精通于蔬菜类制作");
    }
}

Food类

package com.nhjia.pojo.FOOD;

import com.nhjia.pojo.cook.CookWay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component("food1")
/*@Component表明这个类会被扫描*/
public class Food {
	  @Autowired
	/*用于注入,可以通过属性也可以通过名称,这里我们要注入厨师一,因为这里的cookway是属性,cook1具有这个属性,所以ioc把cook1的实例注入到Food中*/
    private CookWay cook = null;
    @Value("猪肉")
    /*@Value表示给这个bean的装配,描述*/
    private String name;
    @Value("红烧肉")
    private String cookingway;
    /* setter and getter */
    public void Cook(){
        System.out.println(this.name+"用于"+this.cookingway+"制作,而");
        cook.cook();
        System.out.println("所以邀请他来做");
    }
}

配置Appconfig.class

package com.nhjia.pojo.test;

import com.nhjia.pojo.FOOD.Food;
import com.nhjia.pojo.cook.cook1;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
/*表示这是一个配置文件*/
@ComponentScan(basePackageClasses = {Food.class, cook1.class})
/*指定包*/
public class Appconfig {
}

最后测试中再加个food1.Cook();

测试结果:Spring IOC容器学习,Bean的学习;

依赖注入成功!

多个依赖注入的bean选择

@Autowired

​ private CookWay cook = null;

CookWay为属性,根据属性寻找bean类;

但是当第二个厨师也加入@Component就会报错;因为具有同种属性的bean有两个,不知道使用哪个;

所以修改方式1:

 	@Autowired
    private CookWay cook1 = null;
/*直接根据Cookway这个属性和cook1这个bean的名称进行匹配*/

方法二:

@Component
@Primary
/*同属性下,有多个类时,Primary具有优先选择权*/
public class cook1 implements CookWay{

}

方法三:也是在有primary存在下,选择cook2的方法

 @Autowired
 @Qualifier("cook1")
 private CookWay cook = null;

带参构造器的装配:

 private CookWay cook = null;
    @Autowired
    public Food(@Qualifier("cook1") CookWay cook){
        this.cook=cook;
    }

使用到的注解:

	@Autowired
	/*用于注入,可以通过属性也可以通过名称,这里我们要注入厨师一,因为这里的cookway是属性,cook1具有这个属性,所以ioc把cook1的实例注入到Food中*/

	@Primary
	/*同属性下,有多个类时,Primary具有优先选择权*/
 	
	@Qualifier("cook1")

后续…

相关标签: Spring学习