Spring IOC 注解annotation的几种方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33642117/article/details/51933810

Spring IOC中的annotation配置有好几种方式~最重要的分别是

@Component

@Resource

@Autowired

它们可以一起使用~

一,那就先说一下@Component如何使用的~

 1 @Component注解可以直接定义bean,而无需在xml定义。但是若两种定义同时存在,xml中的定义会覆盖类中注解的Bean定义。
  2 @Component注解直接写在类上面即可
  3 @Component有一个可选的参数,用于指定 bean 的名称:如@Component("boss")
  4 @Component容易不指定参数,则 bean 的名称为当前类的类名小写
  5 @Component使用之后需要在xml文件配置一个标签: <context:component-scan/>
  6 <context:component-scan base-package="com.briup.ioc.annotation" /> 可以表示spring需要检查哪个包下的java类,看它们是否使用了 @Component注解
  7 @Component定义的bean默认情况下都是单例模式的,如果要让这个bean变为非单例,可以再结合这个 @Scope 注解来达到目标 @Scope("prototype")
  @Component是Spring中所有bean组件的通用形式, @Repository @Service @Controller 则是 @Component的细化,用来表示更具体的用例,分别对应了持久化层、服务层和表现层。但是至少到现在为止这个四种注解的实质区别很小(甚至几乎没有),都是把当前类注册为spring容器中的一个bean。

看个例子:

Boss类:

//相当于配置文件中的<bean name="boss" class="...." ></bean>
<span style="color:#ff0000;">@Scope("prototype")
@Component("boss")</span>
public class Boss {
	private String name;
	private Car car;
	private Office office;
	public Boss(){
		
	}
	
	public Boss(String name, Car car, Office office) {
		this.name = name;
		this.car = car;
		this.office = office;
	}
	
	
	public Boss(Car car, Office office) {
		this.car = car;
		this.office = office;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Car getCar() {
		return car;
	}
	
	
	public void setCar(Car car) {
		this.car = car;
	}
	public Office getOffice() {
		return office;
	}
	
	public void setOffice(Office office) {
		this.office = office;
	}
	
	public void init(){
		System.out.println("初始化..");
	}
	
	public void destroy(){
		System.out.println("销毁");
	}
	
}
Office类:

<span style="color:#ff0000;">@Component("office")</span>
public class Office {
	private String num = "001";
	
	public Office(){
		
	}
	
	public Office(String num) {
		this.num = num;
	}

	public String getNum() {
		return num;
	}

	public void setNum(String num) {
		this.num = num;
	}
	
}

Car类:

<span style="color:#ff0000;">@Component("car")</span>
public class Car {
	private String name;
	private double price;
	
	public Car(){
		
	}
	
	public Car(double price, String name) {
		this.price = price;
		this.name = name;
	}
	
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
三个Bean类都使用了@Component来直接定义bean,在看配置文件annotation.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"
		    xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
   http://www.springframework.org/schema/beans 
   http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context-3.2.xsd">
  <span style="color:#ff0000;"> <!-- 告诉Spring容器要扫描哪些包 -->
   <context:component-scan base-package="com.x.spring.test3.annotation" /></span>
   
   
   <bean name="car" class="com.x.spring.test3.annotation.Car">
       <property name="name" value="BMW"></property>
   </bean>
    <bean name="car2" class="com.x.spring.test3.annotation.Car">
       <property name="name" value="Auto"></property>
   </bean> 
    <bean name="office" class="com.x.spring.test3.annotation.Office">
       <property name="name" value="BEN"></property>
   </bean> 
</beans>
在这个配置文件中又重新定义了bean,所以用了注释的Bean类要以配置文件为准~

测试类:

public class AnnotationTest {

	public static void main(String[] args) {
		//ioc中的注解
		try {
			String path = "com/x/spring/test3/annotation/annotation.xml";
			ClassPathXmlApplicationContext container = 
					new ClassPathXmlApplicationContext(path);
			
			Boss boss = (Boss)container.getBean("boss");
			

		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}
效果图就不贴了~

还可以@Component与@PostConstruct 和 @PreDestroy一起使用~

  @PostConstruct 和 @PreDestroy
  1 标注了 @PostConstruct 注释的方法将在类实例化后调用。
  2 标注了 @PreDestroy 的方法将在类销毁之前调用。
这俩个注释就相当于bean对象的初始化和销毁~

在Boss类加上几行代码,如图:






在测试类加上这行代码:

container.destroy();
看看效果:


效果图果然如我所料,因为Boss类已经是非单例管理的对象了~所以对象的销毁Spring容器管不着~

那接下来就看看@Autowired~

二,@Autowired(与@Component)的使用

 1 @Autowired默认按照byType匹配的方式进行注入,如果没有一个bean的类型是匹配的则会抛异常,
如果有多个bean的类型都匹配成功了,那么再按byName方式进行选择

  2 @Autowired注解可以写在成员变量、set/ger方法、构造器函数上面
  
  3 @Autowired如果最终匹配不成功(注意一定是一个都没有找到的情况)则会抛出异常,
    但是如果设置为@Autowired(required=false),则最终匹配不成功没有不会抛出异常。

  4 @Autowired可以结合 @Qualifier("beanName")来使用,则可以达到byName的效果
  
  5 @Autowired使用后需要在xml文件加入以下配置才能生效:
      <context:annotation-config/>   

不懂byType和byName自动注入的可以去看我的这篇:Spring IOC注入(注入)自动注入


先分析一下@Autowired注解写在成员变量上面:

在Boss类加上这一行代码:


就可以把car对象自动注入进来,因为xml文件有2个car对象,就会按照byName的方式把这个对象自动注入进来,如图:


测试类也加了几行代码:

			System.out.println(boss.getCar());
			System.out.println(boss.getCar().getName());
效果图如下:



再分析把@Autowired注解写在set/get方法上面


效果图跟放在成员变量上面是一样的~

再分析把@Autowired注解写在构造器函数上面


效果图是一样的~

其他的情况我就不一一贴代码了~仔细想想就很容易明白

我们再来分析@Resource吧

三,@Resource(与@Component)的使用

 1 @Resource的作用和 @Autowired差不多,只不过@Resource是默认先用byname,
如果找不到合适的就再用bytype来注入
  2 @Resource有俩个属性,name和type,使用name属性则表示要byName匹配,使用type属性则表示要byType匹配
  3 @Resource使用后需要在xml文件加入以下配置才能生效:
      <context:annotation-config/>   


在Boss类简单的使用一下这个@Resource吧,如图,添加了这一行代码:


这个@Resource默认使用byName方式来进行自动注入的~

在测试类中也加入几行代码:

			System.out.println(boss.getOffice());
			System.out.println(boss.getOffice().getNum());
测试效果如下:


好了,这个注解方式就这样简单~

完整代码如下:

测试类:

public class AnnotationTest {

	public static void main(String[] args) {
		//ioc中的注解
		try {
			String path = "com/x/spring/test3/annotation/annotation.xml";
			ClassPathXmlApplicationContext container = 
					new ClassPathXmlApplicationContext(path);
			
			Boss boss = (Boss)container.getBean("boss");
			
			System.out.println(boss);
			System.out.println(boss.getCar());
			System.out.println(boss.getCar().getName());
			System.out.println(boss.getOffice());
			System.out.println(boss.getOffice().getNum());
			//这行代码在这没用,因为Boss类是非单例管理对象
			container.destroy();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Boss类:

//相当于配置文件中的<bean name="boss" class="...." ></bean>
@Scope("prototype")
@Component("boss")
public class Boss {
	private String name;
	@Autowired
	private Car car;
	@Resource
	private Office office;
	public Boss(){
		
	}
	
	public Boss(String name, Car car, Office office) {
		this.name = name;
		this.car = car;
		this.office = office;
	}
	//@Autowired
	public Boss(Car car, Office office) {
		this.car = car;
		this.office = office;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Car getCar() {
		return car;
	}
	
	//@Autowired
	public void setCar(Car car) {
		this.car = car;
	}
	public Office getOffice() {
		return office;
	}
	
	public void setOffice(Office office) {
		this.office = office;
	}
	@PostConstruct
	public void init(){
		System.out.println("初始化..");
	}
	@PreDestroy
	public void destroy(){
		System.out.println("销毁");
	}
	
}
Office类:

@Component("office")
public class Office {
	private String num = "001";
	
	public Office(){
		
	}
	
	public Office(String num) {
		this.num = num;
	}

	public String getNum() {
		return num;
	}

	public void setNum(String num) {
		this.num = num;
	}
	
}
Car类:

@Component("car")
public class Car {
	private String name;
	private double price;
	
	public Car(){
		
	}
	
	public Car(double price, String name) {
		this.price = price;
		this.name = name;
	}
	
	public double getPrice() {
		return price;
	}
	public void setPrice(double price) {
		this.price = price;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}
配置文件:

<?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-3.2.xsd
   http://www.springframework.org/schema/context 
   http://www.springframework.org/schema/context/spring-context-3.2.xsd">
   <!-- 告诉Spring容器要扫描哪些包 -->
   <context:component-scan base-package="com.x.spring.test3.annotation" />
   
   
   <bean name="car" class="com.x.spring.test3.annotation.Car">
       <property name="name" value="BMW"></property>
   </bean>
    <bean name="car2" class="com.x.spring.test3.annotation.Car">
       <property name="name" value="Auto"></property>
   </bean> 
    <bean name="office" class="com.x.spring.test3.annotation.Office">
       <property name="num" value="123"></property>
   </bean> 
</beans>

最后要注意一点:

 component-scan标签默认情况下自动扫描指定路径下的包(含所有子包),将带有 @Component @Repository @Service @Controller标签的类自动注册到spring容器。对标记了 Spring中的 @Required @Autowired @PostConstruct @PreDestroy @Resource @WebServiceRef @EJB   @PersistenceContext @PersistenceUnit等注解的类进行对应的操作使注解生效(包含了annotation-config标签的作用)



展开阅读全文

没有更多推荐了,返回首页