您的位置:首页 > 编程语言 > Java开发

Spring注解注入

2015-11-30 15:54 627 查看
转自:http://blog.csdn.net/cpf2016/article/details/45582399

1.xml中配置bean

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

[java] view
plaincopy

public class Office {

private String officeNo =”001”;

//省略 get/setter

@Override

public String toString() {

return "officeNo:" + officeNo;

}

}

[java] view
plaincopy

public class Car {

private String brand;

private double price;

// 省略 get/setter

@Override

public String toString() {

return "brand:" + brand + "," + "price:" + price;

}

}

[java] view
plaincopy

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

[html] view
plaincopy

<?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>

这样的话就完成了依赖注入。

测试代码如下:

[java] view
plaincopy

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

[html] view
plaincopy

<!-- 该 BeanPostProcessor 将自动起作用,对标注 @Autowired 的 Bean 进行自动注入 -->

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor"/>

这样,当Spring容器启动时,AutowiredAnnotationBeanPostProcessor将扫描Spring中的所有bean,如果发现bean中拥有@Autowired注解时,就找到何其匹配(默认按类型匹配)的bean,并注入到对应的地方中去。

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

(2)成员变量上使用

[java] view
plaincopy

public class Boss {

@Autowired

private Car car;

@Autowired

private Office office;

@Override

public String toString() {

return "car:" + car + "\n" + "office:" + office;

}

}

beans.xml改为

[html] view
plaincopy

<?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方法上使用

[java] view
plaincopy

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)构造方法上使用

[java] view
plaincopy

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,就会发生异常。

[html] view
plaincopy

<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>

运行后抛出异常

[html] view
plaincopy

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的名称,这样歧义就消除了,可以通过如下方法解决异常

[java] view
plaincopy

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)在配置文件中加入:

[html] view
plaincopy

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

(3)例子

[java] view
plaincopy

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

[html] view
plaincopy

<context:annotation-config/>

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

[html] view
plaincopy

<?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

[html] view
plaincopy

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

2)需要添加命名空间

[html] view
plaincopy

<?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)实例

[java] view
plaincopy

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类

[java] view
plaincopy

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属性的值了,所以直接给成员变量赋值

[java] view
plaincopy

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: