zoukankan      html  css  js  c++  java
  • 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...
    

      

    执行成功!



  • 相关阅读:
    001-导航条悬浮顶部
    000-导航栏单击事件背景变换
    1-MySQL命令行
    了解CentOS服务器的基本信息
    SecureCRT配色
    SecureCRT中文显示乱码
    Android Studio 1.1 使用介绍及导入 jar 包和第三方依赖库
    Android Json 解析
    不断更新中 书签
    Android 常用的权限
  • 原文地址:https://www.cnblogs.com/warrior4236/p/7277153.html
Copyright © 2011-2022 走看看