Spring 使用純注解方式完成IoC


目錄


創建一個簡單的Person類

使用xml方式配置Spring容器並獲取bean的過程

創建xml配置文件

進行測試

使用純注解方式配置Spring容器並獲取bean的過程

創建spring配置類

進行測試

配置注解掃描package

創建帶注解的Person類

創建Spring配置類

使用xml配置注解掃描package

使用注解配置掃描package

使用注解實現注入

對普通數據類型的屬性進行注入

對引用類型的屬性進行注入——構造方法和setter注入

集合數據類型的注入

IoC的相關設置

懶加載

作用域

初始化和銷毀回調程序

 

 


 

 

創建一個簡單的Person類

package cn.ganlixin.pojo;

public class Person {

	private int id;
	private String name;
	private String addr;
	
	// 隱藏了有參和無參構造方法、setter、getter、toString
}

  

 

使用xml方式配置Spring容器並獲取bean的過程

  創建xml配置文件

  如果我們要在Spring容器中創建一個Person類的bean,利用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.xsd">
        
	<bean id="person" class="cn.ganlixin.pojo.Person"></bean>
</beans>

  

  測試代碼

  在測試代碼中,使用ClassPathXmlApplicationContext類來獲取spring上下文,然后通過getBean即可獲取Spring中管理的bean了。

package cn.ganlixin.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.ganlixin.pojo.Person;

public class TestIOC {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
		
		Person bean = context.getBean("person", Person.class);
		System.out.println(bean);
	}
}

  

 

使用純注解方式配置Spring容器並獲取bean的過程

  純注解方法的話,那就舍棄xml配置文件。  

 

創建配置類

  如果我們使用純注解方式實現IoC,那么需要創建一個配置類來代替上面這個xml配置文件,然后就可以不用創建這個xml配置文件了。

package cn.ganlixin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import cn.ganlixin.pojo.Person;

@Configuration
public class MyConfiguration {
	
	@Bean
	public Person person() {
		return new Person();
	}

}

  解釋一下上面這個MyConfiguration類:

  1、創建的配置類,類名隨意,但是需要使用@Configuration注解,標識其為配置類,這個類的功能相當於之前的xml配置文件。

  2、public Person person() 這個方法,使用了@Bean注解,這個方法的功能等同於xml中的<bean>標簽,方法名對應<bean>標簽中的id,方法返回值類型對應<bean>中的class。在方法體中完成對象的實例化即可。

  如果設置bean的id,即不使用方法名作為bean的id,可以在@Bean中直接設置:@Bean("newId")

 

測試代碼

  注意,在測試的時候,因為沒有使用xml配置文件的方式,所以不是使用ClassPathXmlApplicationContext,而是使用AnnotationConfigApplicationContext類,需要接受一個參數,參數就是我們的配置類。

package cn.ganlixin.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import cn.ganlixin.config.MyConfiguration;
import cn.ganlixin.pojo.Person;

public class TestIOC {
	public static void main(String[] args) {
		// 這里使用的是AnnotationConfigApplicationContext
		ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
		
		// 此時的getBean(),第一個參數是MyConfiguration中的某個方法名,因為配置類中的方法名對應<bean>中的id
		Person bean = context.getBean("person", Person.class);
		
		System.out.println(bean);
	}
}

  上面就實現了使用注解方式來完成讓Spring管理bean。

 

 

配置注解掃描package

  前面我們創建了MyConiguration配置類來代替xml配置文件,然后在類中可以定義很多的function來創建對象,每一個function其實是對應一個xml中的一個<bean>標簽的。

  這就意味着,創建每一個bean都需要去Myconfiguration配置類中創建一個function,這樣其實並不方便,所以可以使用包掃描的方式,包掃描的方式就是在MyConfiguration類上使用@ComponentScan注解指定要掃描哪些package,如果那些package中的class上面有@Component、@Service、@Repository、@Controller這幾個注解中的一個,那么spring就會為其創建bean,bean的id默認是類名首字母小寫,但也支持自定義。

  注意,上面列舉了4個注解,@Component、@Service、@Repository、@Controller的功能一樣,都是標識讓Spring管理這些類創建的bean,但是他們的語義是有區別的,所以用法也不相同:

  @Component注解,用來普通的javabean上;最純粹的<bean />

  @Service注解,用在Service層,一般是service.impl包下的類上面;

  @Repository注解,用在數據訪問層,也就是DAO層上

  @Controller注解是用在spring mvc中的控制器上面。

 

創建包含注解的Person類

  創建Person類,包名為cn.ganlixin.pojo。

package cn.ganlixin.pojo;

import org.springframework.stereotype.Component;

@Component  //  使用這個注解,bean的id默認是類名首字母小寫
// @Component("person111") 可以手動設置bean的id
public class Person {

	private int id;
	private String name;
	private String addr;
	
	// 隱藏了有參和無參構造方法、setter、getter、toString
}

  

使用注解配置掃描package

package cn.ganlixin.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@ComponentScan({"cn.ganlixin.pojo", "cn.ganlixin.demo"}) // 指定掃描哪些package
public class MyConfiguration {
	
}
  

  

進行測試

package cn.ganlixin.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import cn.ganlixin.config.MyConfiguration;
import cn.ganlixin.pojo.Person;

public class TestIOC {
	public static void main(String[] args) {
		ApplicationContext context = new AnnotationConfigApplicationContext(MyConfiguration.class);
		
		Person bean = context.getBean("person", Person.class);
		
		System.out.println(bean);
	}
}

  

使用xml配置注解掃描package

  如果要使用配置文件來指定掃描注解的package,需要使用context這個xmlns,下面這個xml配置文件實現了上面MyConfiguration的功能:

<?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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
        
    <!-- 需要使用context這個xmlns,然后使用<context:component-scan>指定需要掃描哪些package -->
	<context:component-scan base-package="cn.ganlixin.pojo, cn.ganlixin.demo"></context:component-scan>
</beans>

  

 

使用注解實現注入

  前面介紹了使用注解來讓Spring容器來管理bean對象,創建bean的時候,默認都是調用無參構造方法。如果我們為對象的屬性賦值,那么就需要進行注入了。

 

對普通數據類型的屬性注入

  這里的普通數據類型是指幾種基本數據類型、以及String,對他們賦值,可以直接使用@Value注解實現。比如下面對Person類的各個屬性進行賦值

package cn.ganlixin.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person {

	@Value("999")
	private int id;
	
	@Value("Jenny")
	private String name;
	
	@Value("America")
	private String addr;
	
	// 隱藏了有參和無參構造方法、setter、getter、toString
}

  上面的@Value注解接收一個字符串類型的值,Spring會根據屬性的類型,自動將字符串類型的值轉換為屬性類型的數據。

  另外,@Value不僅支持直接指定屬性值,使用@Value("${key}")可以讀取外部properties配置文件中的配置項key的值,如果要讀取外部properties配置文件的值,需要借助xml配置Spring,指定外部properties配置文件。

  作為測試,在classpath(src)下創建一個config.properties,添加一項內容:

name=hello world

  修改Spring配置文件:

<?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.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd">
    
    <!-- 指定外部配置文件的路徑 -->
    <context:property-placeholder location="classpath:config.properties" />
        
    <!-- 需要使用context這個xmlns,然后使用<context:component-scan>指定需要掃描哪些package -->
	<context:component-scan base-package="cn.ganlixin.pojo, cn.ganlixin.demo"></context:component-scan>
</beans>

  為Person類中name屬性指定值為外部配置文件的name

package cn.ganlixin.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class Person {

	@Value("999")
	private int id;
	
	@Value("${name}")  // 使用外部配置文件中name的值
	private String name;
	
	@Value("America")
	private String addr;
	
	// 隱藏了有參和無參構造方法、setter、getter、toString
}

  測試:

package cn.ganlixin.test;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import cn.ganlixin.pojo.Person;

public class TestIOC {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
		
		
		Person bean = context.getBean("person", Person.class);
		
		System.out.println(bean);
		// Person [id=999, name=hello world, addr=America]
	}
}

  

對引用數據類型的屬性進行注入——構造方法和setter注入

  對引用數據類型的屬性進行注入時,有兩種方式:構造方法注入和setter注入,如果使用xml配置文件形式,分別是用<constructor-args>和<property>標簽。

  而如果是使用注解的話,那么就有兩個注解可以實現這個功能:@Autowired和@Resource,他們都能實現依賴注入,但是他們也有區別:

  @Resource是Java內置的注解,不能寫在方法上,只能寫在屬性字段上。

  @Autowired是spring提供的注解,即可以寫在屬性字段上,也可以寫在構造方法上,還可以寫在setter上。

package cn.ganlixin.pojo;

import javax.annotation.Resource;

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

@Component
public class Company {
	
	@Resource   // @Resource只能寫在屬性之前
	private Person person1;
	
	@Autowired	// @Autowired可以寫在屬性前
	private Person person;
	
	public Company() {
		super();
	}

	@Autowired	// @Autowired也可以寫在構造方法前,會自動根據所需參數類型進行注入
	public Company(Person person1, Person person) {
		super();
		this.person1 = person1;
		this.person = person;
	}

	@Autowired	// @Autowired還可以寫在setter上
	public void setPerson(Person person) {
		this.person = person;
	}
	
	public void setPerson1(Person person1) {
		this.person1 = person1;
	}

	@Override
	public String toString() {
		return "Company [person1=" + person1 + ", person=" + person + "]";
	}
}

  上面使用@Autowired和@Resource來進行注入的時候,是自動注入的。會根據byName方式,查看spring容器中是否有一個bean的id,該和屬性名稱相同的,如果有的話,就將這個bean注入到屬性中。如果沒有的話,就根據byType進行注入,即根據容器中的bean的type進行匹配,這個時候,如果有多個type相同的bean,就會報錯,需要使用@Qualifier("bean_id")明確指定注入哪一個bean。

 

集合數據類型的注入

  對於集合類型,不建議使用注解方式注入,建議使用xml配置文件方式。

 

 

IoC的相關設置

  除了對bean的注入,還有其他的bean的設置也很重要,比如懶加載、作用域、初始化和銷毀時調用的方法。

 

懶加載

  懶加載在xml配置中是設置bean的lazy-init屬性值,true為設置為懶加載,false為設置為spring容器創建時創建bean,默認不是懶加載。

  可以使用@Lazy注解來設置懶加載,可以在配置類中創建對象的方法上使用,還可以在class的上面設置。

package cn.ganlixin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

import cn.ganlixin.pojo.Person;

@Configuration
public class MyConfiguration {
	
	@Bean
	@Lazy
	public Person person111() {
		return new Person(8888, "xyz", "beijing");
	}
}

  

  還可以在class上設置:

package cn.ganlixin.pojo;

import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
@Lazy
public class Person {
	private int id;
	private String name;
	private String addr;
	
	// 隱藏了有參和無參構造方法、setter、getter、toString
}

  

 

作用域

  作用域在xml中是設置scope屬性,同樣的,在注解中,提供了@Scope與之對應。和@Lazy使用相同,可以在配置類和javabean上使用。

@Component
@Scope("singleton")
public class Person {

}

    

package cn.ganlixin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

import cn.ganlixin.pojo.Person;

@Configuration
@ComponentScan("cn.ganlixin.pojo")
public class MyConfiguration {
	
	@Bean
	@Scope("prototype")
	public Person person() {
		return new Person();
	}
}

  

初始化和銷毀回調程序

  如果是xml配置,可以使用init-method和destroy-method來設置初始話bean和銷毀bean的時候調用。

  如果使用注解,可以實現兩個接口,並重寫兩個方法即可:

package cn.ganlixin.pojo;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

@Component
public class Person implements InitializingBean, DisposableBean{

	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("初始化時被調用");
	}
	
	@Override
	public void destroy() throws Exception {
		System.out.println("被銷毀時調用");
	}
}

  

  如果不實現InitializingBean, DisposableBean接口,可以使用下面這種方式:

package cn.ganlixin.pojo;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.stereotype.Component;

@Component
public class Person{

	@PostConstruct
	public void onInit() {
		System.out.println("初始化時被調用");
	}
	
	@PreDestroy
	public void onDestroy() {
		System.out.println("被銷毀時調用");
	}
	
}

  

  還可以在配置類中進行設置,首先刪除Person中的注解,然后修改配置類:

package cn.ganlixin.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import cn.ganlixin.pojo.Person;

@Configuration
@ComponentScan("cn.ganlixin.pojo")
public class MyConfiguration {
	
	@Bean(initMethod="onInit", destroyMethod="onDestroy")
	public Person person() {
		return new Person();
	}
}

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM