Spring注解注入

1.xml中配置bean

        假如我们现在有3个类,Boss、Office、Car,这3个类需要在Spring容器中配置为bean

public class Office {
    private String officeNo =”001”;

    //省略 get/setter

    @Override
    public String toString() {
        return "officeNo:" + officeNo;
    }
}
public class Car {
    private String brand;
    private double price;

    // 省略 get/setter

    @Override
    public String toString() {
        return "brand:" + brand + "," + "price:" + price;
    }
}
public class Boss {
    private Car car;
    private Office office;

    // 省略 get/setter

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}
           现在在beans.xml中将以上3个类配置成bean

                
<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="boss" class="com.baobaotao.Boss">
        <property name="car" ref="car"/>
        <property name="office" ref="office" />
    </bean>
    <bean id="office" class="com.baobaotao.Office">
        <property name="officeNo" value="002"/>
    </bean>
    <bean id="car" class="com.baobaotao.Car" scope="singleton">
        <property name="brand" value=" 红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>
             这样的话就完成了依赖注入。

             测试代码如下:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class AnnoIoCTest {

    public static void main(String[] args) {
        String[] locations = {"beans.xml"};
        ApplicationContext ctx = 
		    new ClassPathXmlApplicationContext(locations);
        Boss boss = (Boss) ctx.getBean("boss");
        System.out.println(boss);
    }
}
               控制台正确打出了Boss的信息,说明Spring已经正确完成了实例的注入

2.@Autowired

        (1)要求

               Spring通过一个BeanPostProcessor对@Autowired进行解析,要使@Autowired起作用,则必须在Spring容器中声明AutowiredAnnotationBeanPostProcessor的Bean

 <!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->    
 <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
               这样,当Spring容器启动时,AutowiredAnnotationBeanPostProcessor将扫描Spring中的所有bean,如果发现bean中拥有@Autowired注解时,就找到何其匹配( 默认按类型匹配)的bean,并注入到对应的地方中去。

          如果是在成员变量上使用的话:因为是直接使用反射对bean中的私有成员变量进行注入的,所以使用了@Autowired注解之后,可以直接删除setter方法

        (2)成员变量上使用

public class Boss {
	@Autowired
    private Car car;
	@Autowired
    private Office office;

	@Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}
               beans.xml改为

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
 
    <bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>
 
    <bean id="boss" class="com.mycompany.app.Boss">
    </bean>
    <bean id="office" class="com.mycompany.app.Office">
        <property name="officeNo" value="002"/>
    </bean>
    <bean id="car" class="com.mycompany.app.Car" scope="singleton">
        <property name="brand" value=" 红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>
                结果为:

car:brand: 红旗 CA72,price:2000.0
office:officeNo:002

        (3)set方法上使用

package com.mycompany.app;

import org.springframework.beans.factory.annotation.Autowired;

public class Boss {
    private Car car;
    private Office office;

    @Autowired
	public void setCar(Car car) {
		this.car = car;
	}

    @Autowired
	public void setOffice(Office office) {
		this.office = office;
	}

	@Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}

        这时,@Autowired将查找被标注的方法的传入参数类型的bean,并调用方法自动注入这些bean 

       (4)构造方法上使用

package com.mycompany.app;

import org.springframework.beans.factory.annotation.Autowired;

public class Boss {
    private Car car;
    private Office office;

   
    @Autowired
    public Boss(Car car, Office office) {
		super();
		this.car = car;
		this.office = office;
    }

	@Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}
          由于Boss构造方法有两个入参,分别是car和office,@Autowired将分别寻找和他们类型匹配的bean,将他们作为入参来创建Boss bean

3.@Qualifier

        (1)引入及作用

                  当我们在Spring容器中配置了2个类型为Office类型的bean,当对Boss的office成员变量进行自动注入时,Spring容器将无法确定到底使用哪一个bean,就会发生异常。

    <bean id="boss" class="com.mycompany.app.Boss">
    </bean>
    <bean id="office1" class="com.mycompany.app.Office">
        <property name="officeNo" value="002"/>
    </bean>
     <bean id="office2" class="com.mycompany.app.Office">
        <property name="officeNo" value="004"/>
    </bean>
              运行后抛出异常

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.mycompany.app.Office] is defined: expected single matching bean but found 2: [office1, office2]

                 Spring中允许我们通过@Qualifier注释指定注入bean的名称,这样歧义就消除了,可以通过如下方法解决异常

package com.mycompany.app;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class Boss {
    @Autowired
    private Car car;
    @Autowired
    @Qualifier("office1")
    private Office office;

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}
             

4.@Resource

        (1)作用

                   @Resource作用相当于@Autowired,只不过 @Autowired按byType自动注入,@Resource按byName自动注入

                   @Resource有两个比较重要的属性:name和type,Spring将@Resource注释的name属性解析为bean的名字,而type属性解析为bean的类型。

                   所以,如果使用name属性,则使用byName的自动注入策略,而使用type属性时则使用byType自动注入策略。如果不指定name和type,则将通过反射来使用byName自动注入

        (2)使用要求

                   1)@Resource位于common-annotation.jar中,因此在使用之前必须要导包

                   2)在配置文件中加入:

    <bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>

        (3)例子     

public class Boss {
    @Resource
    private Car car;
    @Resource
    private Office office;

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}

5.spring中隐式注册注解

        使用这些注解时需要在配置文件中导入很多配置,这样会导致配置文件混乱,所以spring提供了一个方法,可以隐式注册这些annotation

<context:annotation-config/>
        但是需要导入context命名空间,所以,需要再加入context明明空间。整体配置如下:

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
    <context:annotation-config/> 
    <bean id="boss" class="com.mycompany.app.Boss">
    </bean>
    <bean id="office" class="com.mycompany.app.Office">
        <property name="officeNo" value="002"/>
    </bean>
     <bean id="office2" class="com.mycompany.app.Office">
        <property name="officeNo" value="004"/>
    </bean>
    <bean id="car" class="com.mycompany.app.Car" scope="singleton">
        <property name="brand" value=" 红旗 CA72"/>
        <property name="price" value="2000"/>
    </bean>
</beans>
          这个隐式配置实际上注册了4个类:

AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 以及equiredAnnotationBeanPostProcessor 


6.@Component

        (1)引入

                   虽然我们可以通过@Autowired或者@Resource在bean类中使用自动注入功能,但是bean还是在xml文件中通过<bean>进行了定义——也就是说,在xml配置文件中定义bean,通过@Autowired或者@Resource为bean的成员变量、方法、构造方法入参提供自动注入的功能。

                  那么能否也通过注释定义bean,从xml配置中完全移除bean定义的配置呢?答案是肯定的。我们通过@Component注解就可以达到这个目标了。

                  实际上共有四种注解实现了这种功能@Component、@Repository、@Controller、@Service,功能完全相同,只是应用于不同的层次

                        @Component:是一个泛化的概念,仅仅表示是一个bean,可以用在任何层次

                        @Service:通常用在业务层,功能与@Component相同

                        @Controller:通常用在控制层,功能与@Component相同

                        @Repository:通常用在dao层,功能与@Component相同

        (2)配置
                  1)需要指定扫描的包,这样的话spring就可以自动扫描指定包下带@Component(或其他三个)注解的类,并生成bean

<context:component-scan base-package="com.mycompany.app"/>

                  2)需要添加命名空间

<?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-2.5.xsd">
        (3)实例

package com.mycompany.app;

import javax.annotation.Resource;

import org.springframework.stereotype.Component;

@Component
public class Boss {
    @Resource
    private Car car;
    @Resource
    private Office office;

    @Override
    public String toString() {
        return "car:" + car + "\n" + "office:" + office;
    }
}
         car类

package com.mycompany.app;

import org.springframework.stereotype.Component;

@Component
public class Car {
    private String brand = "红旗 CA72";
    private double price = 2000;

    @Override
    public String toString() {
        return "brand:" + brand + "," + "price:" + price;
    }

	public String getBrand() {
		return brand;
	}

	public void setBrand(String brand) {
		this.brand = brand;
	}

	public double getPrice() {
		return price;
	}

	public void setPrice(double price) {
		this.price = price;
	}
}
             注意:这里因为不能再在bean中指定car属性的值了,所以直接给成员变量赋值
package com.mycompany.app;

import org.springframework.stereotype.Component;

@Component
public class Office {
    private String officeNo ="001";


    public String getOfficeNo() {
		return officeNo;
	}


	public void setOfficeNo(String officeNo) {
		this.officeNo = officeNo;
	}


    @Override
    public String toString() {
        return "officeNo:" + officeNo;
    }
}

        (4)@Scope
                  @Scope注解可以和@Component注解配合使用,用来指定bean的scope。

                  默认是singleton,也就是整个应用使用同一个实例;如果使用prototype,则spring每次getBean都会拿到新的bean


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值