Bean的配置
继续引用spring中的java基础(注解)的例子代码person类和air接口。
1、基于XML配置Bean
Spring通过
2、使用注解定义Bean
使用xml配置的时候,定义bean和实现bean是分离的,而用注解定义bean时,只要在bean实现类上标注注解就能实现配置bean。
@Component
public class CleanAir implements IAir {
@Override
public String toString(){
return "CleanAir";
}
}
使用@Component注解在CleanAir类声明处对类进行标注,它可以被Spring容器识别,自动将POJO类转换为容器管理的bean。他和1、中的xml配置是等效的。定义Bean的注解还提供了其他3个功能与@Component等效的注解
- @Repository:用于对DAO实现类进行标注。
- @Service:用于对Service实现类进行标注。
- @Controller:用于对Controller实现类进行标注。
3、基于Java类提供Bean定义
在普通的pojo类中标注@Configuration注解,相当于一个xml文件配置,每个@Bean注解,相当于一个
@Configuration
public class AppConf {
@Bean
public CleanAir cleanAir(){
return new CleanAir();
}
@Bean
public DirtyAir dirtyAir(){
return new DirtyAir();
}
@Bean
public Person person(){
return new Person(dirtyAir());
}
}
public static void main(String [] args){
ApplicationContext ac =
new AnnotationConfigApplicationContext(AppConf.class);
Person person1 = ac.getBean(Person.class);
person1.Breath();
}
Bean的注入
Bean的注入方式有两种:一种是在XML中配置,另一种是使用注解的方法注入
1、XML方式注入
1)属性注入
对类中的字段进行注入,在传统的对象实例化可以使用new,再进行set方法来设置字段的值,在Spring中,可以使用property来进行属性注入,需要有字段对应的set方法。
新建XMLInstance类
public class XMLInstance {
private String name;
public void setName(String name ){
this.name = name;
}
private IAir iAir;
public void setAir(IAir iAir){
this.iAir = iAir;
}
public void Breath(){
System.out.println("Name:"+this.name+"\nAir:"+this.iAir.toString());
}
}
在XMLInstance中已设置了set方法,可以使用XMLproperty来配置属性,name表示属性名,value用来设置基本类型的属性值,ref标签配置非基本类型的属性值。XML配置如下。
运行输出
Name:abc
Air:CleanAir
2)构造函数注入
在属性注入时先使用默认的无参构造函数,再使用set,在使用有参构造函数时进行的属性注入,就是构造函数注入,在1)中增加一个构造函数,在XMLInstance类中增加如下代码
public XMLInstance(String name,IAir iAir){
super();
this.name = name;
this.iAir = iAir;
}
在XML中使用construect-arg来设置构造函数的参数,index代表参数的顺序位置,value设置构造参数的基本类型,ref引用非基本类型的bean的id。XML配置如下。
运行输出
Name:def
Air:CleanAir
3)工厂方法注入
工厂方法注入参考的工厂设计模式,通过工厂类来实现对象的实例化,工厂方法有静态与非静态方法。新建一个工厂类。
public class XMLFactory {
public XMLInstance CreateInstance(){
return new XMLInstance("instance",new CleanAir());
}
public static XMLInstance CreateStaticInstance(){
return new XMLInstance("static instance",new CleanAir());
}
}
可见工厂类中有静态方法和非静态方法,静态时不需要实例化工厂类直接调用静态工厂方法,非静态需要实例化工厂类再调用工厂方法。XML配置如下。
运行结果
Name:static instance
Air:CleanAir
Name:instance
Air:CleanAir
4)常见数据类型注入
已有类型注入
常见数据类型有List、Set、Map、Properties。
新建XmlCollectionsDemo类,为这四种类型进行数据注入。
public class XmlCollectionsDemo {
private List
XML配置
1
prokeyA
prokeyB
运行结果
[1, CleanAir, CleanAir]
{prokey2=prokeyB, prokey1=prokeyA}
[1, CleanAir, CleanAir]
{key1=1, key2=CleanAir, key3=CleanAir}
自定义属性编辑器
有一些属性是没法注入的,比如说日子。但可以通过PropertyEditorySupport,重写setAsText方法来实现注入。新建CustomerProperty类
public class CustomerProperty extends PropertyEditorSupport {
private String format = "yyyy-MM-dd";
public String getFormat(){
return format;
}
public void setFormat(String format){
this.format = format;
}
@Override
public void setAsText(String text) throws IllegalArgumentException{
SimpleDateFormat sdf = new SimpleDateFormat(format);
try{
this.setValue(sdf.parse(text));
}catch (Exception e){
e.printStackTrace();
}
}
}
该类中将日期以String的形式传入,再重写了setAsText方法,setAsText方法会自动执行转换成日期类重新赋值给传入的value,在XML配置中,相当于import,将Date类引用到customEditors中。将4)中XmlCollectionsDemo添加字段Date,并在xml中增加
运行结果
[1, CleanAir, CleanAir]
{prokey2=prokeyB, prokey1=prokeyA}
[1, CleanAir, CleanAir]
{key1=1, key2=CleanAir, key3=CleanAir}
Mon Aug 12 00:00:00 CST 2019
5)初始化函数、销毁函数
在某些对象实例化完毕后还需要执行某些初始化代码,但由于某些原因并不能写在构造函数中,这个时候可以使将初始化代码写到另一个方法中,将init-method属性设置为该方法,有的对象使用完毕之后需要释放操作,可以用destroy-method设置销毁方法
在XMLInstance类中增加初始化方法和销毁方法
public void DestroyMethod(){
System.out.println("DestroyMethod");
}
public void InitMethod(){
System.out.println("InitMethod");
}
并在XML中注入初始化方法和销毁方法,修改xml
这样在创建实例后会输出InitMethod,在执行销毁之后会输出DestroyMethod。
2、注解方式注入
1)常用注解
- @Autowired:默认按类型匹配注入bean,可以对类成员变量、方法和构造函数进行标注,完成自动装配的工作。在使用该注解时,会在容器中查询对应类型的bean。如果查询结果刚好为一个,就将该bean装配给他指定的数据:如果查询结果不止一个,会按照名称来查找,如果查询结果为空,会抛出异常。
- @Required:适用于bean属性的setter方法,并表示受影响的bean属性必须在XML配置文件在配置时进行填充:否则会抛出一个异常。
- @Qualifier:@Autowird为单实例的,但通常在面向接口编程中,一个接口会有可能有多个实现,这个时候@Qualifier可选择用哪个实现进行注入。
- @Value:等效于property中的value设置。
- @Resource:默认按名称匹配注入bean。要求提供一个bean名称,如果没有提供bean名称,会自动采用标注处的变量名或方法名作为bean的名称,如果没有指定bean的名字,同时Spring容器中又没有该名字的bean.这时@Resource会退回为@Autowired按类型匹配注入。
新建一个AnnontationInstance类
@Component
public class AnnontationInstance {
@Value("789")
private String name;
public void setName(String name){
this.name = name;
}
@Autowired
@Qualifier(value = "cleanair")
private IAir air;
// @Resource(name = "CleanAir")
public void setAir(IAir air){
this.air = air;
}
public void Breath(){
System.out.println("Name:"+this.name+"\nAir:"+this.air.toString());
}
}
注:@Autowired和@Qualifier是可以与@Resource相互代替使用的,但是在@Resource中使用的是name是bean的id,而@Qualifier中的valu使用的是bean的qualifier。
回顾xml
在配置完注解之后,还要告诉Spring开启注解,这样自动装配的注解才会生效,可以使用component-scan或者annotation-config来启用注解