spring扩展的常用接口

一:ApplicationContextAware接口

实现ApplicationContextAware接口,重写setApplicationContext方法,可以将spring容器上下文对象注入,

然后持有spring上下文对象,可以通过该对象获取spring容器中注册的任何bean实例。

/**
 * @author Administrator
 * 实现ApplicationContextAware接口,重写setApplicationContext方法,会注入
 * spring上下文对象,可以在程序中持有一个context的对象,通过context,我们可以获取任何
 * spring容器管理的bean
 */
public class ApplicationContextUtils implements ApplicationContextAware{
	
	private static ApplicationContext context;
	
	@Override
	public void setApplicationContext(ApplicationContext context) throws BeansException {
		ApplicationContextUtils.context = context;
	}
	
	public static ApplicationContext getApplicationContext(){
		return context;
	}
	
	/**
	 * 通过beanName获取实例bean
	 * @param beanName
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(String beanName){
		return (T) context.getBean(beanName);
	}
	
	/**
	 * 通过类型获取实例bean,但是如果在spring容器中通过相同的类
	 * 的不同构造器创建两个不同的对象,通过类型则获取不到对象
	 * @param clazz
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public static <T> T getBean(Class<?> clazz){
		return (T) context.getBean(clazz);
	}
	
}

  

测试两种获取实例bean的方式:

@Test
	public void testAppContext() {
		String conf = "applicationContext.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(conf);
		Emp emp = ApplicationContextUtils.getBean("emp");
		System.out.println(emp);
		Emp emp2 = ApplicationContextUtils.getBean(Emp.class);
		System.out.println(emp2);
	}

  

Emp [name=null, age=null, salary=null]
Emp [name=null, age=null, salary=null]

 可以获取对象,但是如果xml中注册两个相同类型的bean,就会出问题:

<!-- 实例化对象,默认调用无参数构造器 -->
    <bean id="emp" class="com.hlcui.entity.Emp" init-method="init"></bean>
    
    <!-- 实例化对象,有参数构造器 -->
    <bean id="emp2" class="com.hlcui.entity.Emp">
    	<property name="name" value="Tom"></property>
    	<property name="age" value="12"></property>
    	<property name="salary" value="14000.0"></property>
    </bean>

 

实现ApplicationContextAware接口的同时,还要将类 ApplicationContextUtils 交给spring容器管理,这样在

spring容器启动的时候才会将该对象注册,当检测到该类实现该接口时,会把spring上下文对象注入。

下面看一下接口源码:

public interface ApplicationContextAware
    extends Aware
{

    public abstract void setApplicationContext(ApplicationContext applicationcontext)
        throws BeansException;
}

 ApplicationContextAware接口内部只有一个抽象方法setApplicationContext(),同时又继承Aware接口

Aware接口:

public interface Aware
{
}

 空接口,就是一个标记

二:InitializingBean接口

实现该接口的类,需要重写 afterPropertiesSet() ,在实例化的时候,调用完构造方法创建对象之后,会调用

该方法执行一个初始化bean的动作,作用类似@PostContrcut注解和xml中配置的init-method属性,但是执行顺序

有区别

/**
 * @author Administrator
 * 员工Emp类,实现InitializingBean接口,重写afterPropertiesSet方法,还有注解@PostConstruct,同时还有
 * 在实例化Emp的时候,配置了init-method="init"属性
 */
public class Emp implements InitializingBean{
	
	private String name;
	
	private Integer age;
	
	private Double salary;
	
	public Emp(){
		System.out.println("constructor...");
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		System.out.println("InitializingBean...afterPropertiesSet");
	}

	@PostConstruct
	public void reload(){
		System.out.println("@PostConstruct");
	}
	
	public void init(){
		System.out.println("method-init");
	}
	
	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public Double getSalary() {
		return salary;
	}

	public void setSalary(Double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Emp [name=" + name + ", age=" + age + ", salary=" + salary + "]";
	}
	
	
}

  

spring容器xml中配置:

<!-- 该配置扫描注解到spring容器 -->
    <context:annotation-config/>
    
    <bean id="applicationContextUtils" class="com.hlcui.util.ApplicationContextUtils"></bean>
    
    <!-- 实例化对象,默认调用无参数构造器 -->
    <bean id="emp" class="com.hlcui.entity.Emp" init-method="init"></bean>
    
    <!-- 实例化对象,有参数构造器 -->
    <bean id="emp2" class="com.hlcui.entity.Emp">
    	<property name="name" value="Tom"></property>
    	<property name="age" value="12"></property>
    	<property name="salary" value="14000.0"></property>
    </bean>
    

  

 <context:annotation-config/> 的作用是扫描注解到spring容器,但是它的作用有限制,不能用作扫描service,controller,component等
组件注册到spring,例如:<context:component-scan = "com.hlcui.*"/> 它的作用是扫描组件,包括上面的配置。

执行结果如下:

constructor...
@PostConstruct
InitializingBean...afterPropertiesSet
method-init
constructor...
@PostConstruct
InitializingBean...afterPropertiesSet

  首先执行第一条:

<bean id="emp" class="com.hlcui.entity.Emp" init-method="init"></bean>
1:执行构造器,创建对象
2:创建对象之后,调用有@PostContruct注解的方法初始化bean对象
3:调用afterProptertiesSeet方法初始化对象
4:调用xml中配置的init-method方法初始化对象

执行第2条语句:
<bean id="emp2" class="com.hlcui.entity.Emp"> <property name="name" value="Tom"></property> <property name="age" value="12"></property> <property name="salary" value="14000.0"></property> </bean>
1:执行构造器,创建对象
2:创建对象之后,调用有@PostContruct注解的方法初始化bean对象
3:调用afterProptertiesSeet方法初始化对象

这里创建完对象之后,有一个set注入的过程,会调用Emp类中的set*方法,对对象进行初始化,然后
在调用2,3步骤。

假如把Emp对象中set方法注释,那么第2条语句执行完创建对象之后,就会停止。


三:注入List<接口> 对象
如果在一个类里面需要依赖多个bean对象时,可以通过实现接口的方式,将所有的bean注入,方式如下:
/**
 * @author Administrator
 * IBusinessService接口是一个空接口,作为一个标记
 */
public interface IBusinessService {
	public abstract void execute();
}

  

/**
 * @author Administrator
 *
 */
@Component
public class ABusinessServiceImpl implements IBusinessService{

	@Override
	public void execute() {
		System.out.println("ABusinessServiceImpl...");
	}

}

  

@Component
public class BBusinessServiceImpl  implements IBusinessService{
	@Override
	public void execute() {
		System.out.println("BBusinessServiceImpl...");
	}
}

  

@Component
public class CBusinessServiceImpl  implements IBusinessService{
	@Override
	public void execute() {
		System.out.println("CBusinessServiceImpl...");
	}
}

  

在*handler类中依赖上面3个类

@Component
public class BusinessServiceHandler {
	
	@Autowired
	private List<IBusinessService> services;
	
	public void handler(){
		for(IBusinessService s:services){
			s.execute();
		}
	}
}

  

测试注入效果:

@Test
	public void testAppContext() {
		String conf = "applicationContext.xml";
		ApplicationContext context = new ClassPathXmlApplicationContext(conf);
		BusinessServiceHandler bhandler = ApplicationContextUtils.getBean("businessServiceHandler");
		bhandler.handler();
	}

  

ABusinessServiceImpl...
BBusinessServiceImpl...
CBusinessServiceImpl...

  

执行成功!



原文地址:https://www.cnblogs.com/warrior4236/p/7277153.html