Spring IOC容器学习,Bean的学习;
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());
}
}
输出结果:
但是第一种方式,如果有很多种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();
测试结果:
依赖注入成功!
多个依赖注入的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")
后续…
下一篇: 孙贲:孙策的弟弟,东汉末年著名将领