(spring)Bean的配置与注入

Bean的配置

继续引用spring中的java基础(注解)的例子代码person类和air接口。

1、基于XML配置Bean

Spring通过配置来实例化、设置Bean的属性以及设置bean的相互依赖,有id和class的属性,class相当于我们new来创建新实例时所需要导入的类,而id相当于创建new时的对象名。class是必须的,id是非必须的,但在配置文件中配置其他bean时引用该bean时,该bean也必须要有定义id。


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 list;
    private Properties pros;
    private Set sets;
    private Map maps;
    public List getList() {
        return list;
    }
    public void setList(List list) {
        this.list = list;
    }
    public Properties getPros() {
        return pros;
    }
    public void setPros(Properties pros) {
        this.pros = pros;
    }
    public Set getSets() {
        return sets;
    }
    public void setSets(Set sets) {
        this.sets = sets;
    }
    public Map getMaps() {
        return maps;
    }
    public void setMaps(Map maps) {
        this.maps = maps;
    }
    public static void main(String[] args){
        ApplicationContext ac = new ClassPathXmlApplicationContext("META-INF/model.xml");
        BeanFactory factory = ac;
        XmlCollectionsDemo xmlCollectionsDemo
                = (XmlCollectionsDemo)factory.getBean("xmlCollectionsDemo");
        System.out.println(xmlCollectionsDemo.getList());
        System.out.println(xmlCollectionsDemo.getPros());
        System.out.println(xmlCollectionsDemo.getSets());
        System.out.println(xmlCollectionsDemo.getMaps());
        System.out.println(xmlCollectionsDemo.getDate());
    }
}

XML配置



        
            
                1
                
                
            
        
        
        
            
                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来启用注解

 

你可能感兴趣的:((spring)Bean的配置与注入)