美文网首页
spring源码学习之Aware分析

spring源码学习之Aware分析

作者: 会上树的程序猿 | 来源:发表于2019-07-30 22:19 被阅读0次

还记的我们在#CreateBean(...)方法中其中有一个过程是初始化bean的过程,在初始化的方法中我们其中有一个过程是激活Aware的方法的过程,这节我们来看看Aware到底是什么

Aware接口

该接口位于org.springframework.beans.factory包下

/**
 * A marker superinterface indicating that a bean is eligible to be notified by the
 * Spring container of a particular framework object through a callback-style method.
 * The actual method signature is determined by individual subinterfaces but should
 * typically consist of just one void-returning method that accepts a single argument.
 *
 * <p>Note that merely implementing {@link Aware} provides no default functionality.
 * Rather, processing must be done explicitly, for example in a
 * {@link org.springframework.beans.factory.config.BeanPostProcessor}.
 * Refer to {@link org.springframework.context.support.ApplicationContextAwareProcessor}
 * for an example of processing specific {@code *Aware} interface callback
 */
  public interface Aware {

}

该接口主要的作用是一个标记超级接口,实现了该接口的bean是具有回调spring容器的能力,我们可以看到,是一个空接口,实际方法的签名是由各个子接口来实现,通常只接受返回单个参数的seter方法,我们来看一下我们的激活Aware方法的代码:

AbstractAutowireCapableBeanFactory.java
private void invokeAwareMethods(final String beanName, final Object bean) {
    if (bean instanceof Aware) {
        if (bean instanceof BeanNameAware) {
            ((BeanNameAware) bean).setBeanName(beanName);
        }
        if (bean instanceof BeanClassLoaderAware) {
            ClassLoader bcl = getBeanClassLoader();
            if (bcl != null) {
                ((BeanClassLoaderAware) bean).setBeanClassLoader(bcl);
            }
        }
        if (bean instanceof BeanFactoryAware) {
            ((BeanFactoryAware) bean).setBeanFactory(AbstractAutowireCapableBeanFactory.this);
        }
    }
}

代码简单:

  • 如果是BeanNameAware类型的话,调用setXX方法设置属性
  • 如果是BeanClassLoaderAware类型的话,调用setBeanClassLoader设置属性
  • 如果是beanFactoryAware类型的话,调用setBeanFactory设置属性
Aware的实现类

我们来看一下实现了Aware接口的子类

image

这只是其中的一部分实现,图来自大佬芋艿的博客,大家可以去看看,接下来我们自己可以实现自己的Aware方法:

''''''
public interface BeanClassLoaderAware extends Aware {

/**
* 将 BeanClassLoader 提供给 bean 实例回调
* 在 bean 属性填充之后、初始化回调之前回调,
* 例如InitializingBean的InitializingBean.afterPropertiesSet()方法或自定义init方法
*/
void setBeanClassLoader(ClassLoader classLoader);


public interface BeanFactoryAware extends Aware {

   /**
* 将 BeanFactory 提供给 bean 实例回调
* 调用时机和 setBeanClassLoader 一样
*/
void setBeanFactory(BeanFactory beanFactory) throws BeansException;

public interface BeanNameAware extends Aware {

/**
* 在创建此 bean 的 bean工厂中设置 beanName
*/
void setBeanName(String name);

}


public interface ApplicationContextAware extends Aware {

/**
 * 设置此 bean 对象的 ApplicationContext,通常,该方法用于初始化对象
 */
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;

常见的四种实现Aware接口的子类,我们来看case

  public class MyAwareCase implements
    BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, ApplicationContextAware {

private String beanName;
private ClassLoader classLoader;
private BeanFactory beanFactory;
private ApplicationContext applicationContext;
public void setBeanClassLoader(ClassLoader classLoader) {

    this.classLoader = classLoader;
    System.out.println("调用:BeanClassLoaderAware的setBeanClassLoader方法");

}

public void setBeanFactory(BeanFactory beanFactory) throws BeansException {

    this.beanFactory = beanFactory;
    System.out.println("调用:BeanFactoryAware的setBeanFactory方法");

}

public void setBeanName(String name) {
    this.beanName = name;
    System.out.println("调用:BeanNameAware的setBeanName方法");

}

public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {

    this.applicationContext = applicationContext;
    System.out.println("调用:ApplicationContextAware的setApplicationContext方法");

}

public void display(){
    System.out.println("beanName:" + beanName);
    System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));
    System.out.println("系统环境为:" + applicationContext.getEnvironment());
}

测试方法如下:

public class AwareTest {

public static void main(String[] args) {

    ClassPathResource resource = new ClassPathResource("awareConfig.xml");
    DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
    XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
     reader.loadBeanDefinitions(resource);
    MyAwareCase myAwareCase = (MyAwareCase)factory.getBean("myAwareCase");
    myAwareCase.display();
}

配置文件如下:

<?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="myAwareCase" class="com.sgcc.aware.MyAwareCase">
    <property name="beanName" value="beanName"/>
    <property name="beanFactory" value="beanFactory"/>
    <property name="beanClassLoader" value="beanClassLoader"/>
    <property name="applicationContext" value="applicationContext"/>
</bean>
</beans>

很意外,我运行时报了一个错误,大概知道问题所在,这里我把错误贴出来,有知道解决的可以留个言,在这里我先谢过了

Caused by: org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.lang.String' to required type 'org.springframework.beans.factory.BeanFactory' for property 'beanFactory'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.lang.String' to required type 'org.springframework.beans.factory.BeanFactory' for property 'beanFactory': no matching editors or conversion strategy found
at org.springframework.beans.AbstractNestablePropertyAccessor.convertIfNecessary(AbstractNestablePropertyAccessor.java:590)
at org.springframework.beans.AbstractNestablePropertyAccessor.convertForProperty(AbstractNestablePropertyAccessor.java:604)
at org.springframework.beans.BeanWrapperImpl.convertForProperty(BeanWrapperImpl.java:219)

从异常信息来看是因为属性beanFactory在匹配类型的过程中出现的问题.它需要的是一个BeanFactory类型的属性value,我这里是String,可能是这个原因造成的

总结

经过简单的case,我们发现Aware接口的实质,spring主要来检测当前bean是否实现了Aware接口,如果实现了,则通过setxxx设置对应的属性给bean,之后我们的bean就有了从spring容器中获取资源的权限了......

相关文章

网友评论

      本文标题:spring源码学习之Aware分析

      本文链接:https://www.haomeiwen.com/subject/lloirctx.html