spring学习(六)——1.1 Aware 接口

参考文章:

http://www.iocoder.cn/

 

初始化Bean的主要方法在AbstractAutowireCapableBeanFactory.doCreateBean方法中的initializeBean执行,源码逻辑;

protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
		//安全模式
		if (System.getSecurityManager() != null) {
			// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
			AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
				invokeAwareMethods(beanName, bean);
				return null;
			}, getAccessControlContext());
		}
		else {
			// 激活 Aware 方法,对特殊的 bean 处理:Aware、BeanClassLoaderAware、BeanFactoryAware
			invokeAwareMethods(beanName, bean);
		}

		Object wrappedBean = bean;
		if (mbd == null || !mbd.isSynthetic()) {
			// 初始化 bean的前置处理
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}

		try {
			// 激活初始化方法
			invokeInitMethods(beanName, wrappedBean, mbd);
		}
		catch (Throwable ex) {
			throw new BeanCreationException(
					(mbd != null ? mbd.getResourceDescription() : null),
					beanName, "Invocation of init method failed", ex);
		}
		if (mbd == null || !mbd.isSynthetic()) {
			// 初始化bean的后置处理
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}

		return wrappedBean;
	}

 

里面主要有三件事:

  1. 激活 Aware 方法
  2. 后置处理器的应用
  3. 激活自定义的 init 方法

这篇文章先分析第一个激活Aware

Aware接口

接口定义

/**
 * Aware 接口为 Spring 容器的核心接口,是一个具有标识作用的超级接口,
 * 实现了该接口的 bean 是具有被 Spring 容器通知的能力
 */
public interface Aware {

}

接口常见命名

Aware 接口是一个空接口,实际的方法签名由各个子接口来确定,且该接口通常只会有一个接收单参数的 set 方法,该 set 方法的命名方式为 set + 去掉接口名中的 Aware 后缀。

即 XxxAware 接口,则方法定义为 setXxx(),例如 BeanNameAware(setBeanName)

接口使用策略

Aware 类接口的 setXxx 方法其实就是设置 xxx 属性值的。 Spring 容器中是实现感知并设置属性值的逻辑是在invokeAwareMethods方法中

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

接口的部分实现类

spring的激活Aware主要涉及的几个接口:

  1. BeanClassLoaderAware :将 BeanClassLoader 提供给 bean 实例回调
  2. BeanFactoryAware:将 BeanFactory 提供给 bean 实例回调
  3. BeanNameAware :在创建此 bean 的 bean工厂中设置 beanName

 

Aware接口使用的Demo

自定义一个接口

/**
 * @author daify
 * @date 2019-03-18
 */
public class MyAware implements BeanNameAware,BeanFactoryAware,BeanClassLoaderAware,ApplicationContextAware {

    private String beanName;

    private BeanFactory beanFactory;

    private ClassLoader classLoader;

    private ApplicationContext applicationContext;

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println("调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法");
        this.classLoader = classLoader;
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("调用了 BeanFactoryAware 的 setBeanFactory 方法");
        this.beanFactory = beanFactory;
    }

    @Override
    public void setBeanName(String s) {
        System.out.println("调用了 BeanNameAware 的 setBeanName 方法");
        this.beanName = s;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("调用了 ApplicationContextAware 的 setApplicationContext 方法");
        this.applicationContext = applicationContext;
    }

    public void display(){
        System.out.println("beanName:" + beanName);
        System.out.println("是否为单例:" + beanFactory.isSingleton(beanName));
    }
}

测试类分为两种

1、加载资源后,放入bean工厂

public class MyAwareTest01 {

    public static void main(String[] args) {
        ClassPathResource resource = new ClassPathResource("spring.xml");
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(factory);
        reader.loadBeanDefinitions(resource);

        MyAware applicationAware = (MyAware) factory.getBean("myAware");
        applicationAware.display();
    }
}

打印结果

调用了 BeanNameAware 的 setBeanName 方法
调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法
调用了 BeanFactoryAware 的 setBeanFactory 方法
00:07:06.945 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'myAware'
beanName:myAware
是否为单例:true

2、将资源加载进application中

/**
 * @author daify
 * @date 2019-03-18
 */
public class MyAwareTest02 {

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        MyAware applicationAware = (MyAware) applicationContext.getBean("myAware");
        applicationAware.display();
    }
}

打印结果

调用了 BeanNameAware 的 setBeanName 方法
调用了 BeanClassLoaderAware 的 setBeanClassLoader 方法
调用了 BeanFactoryAware 的 setBeanFactory 方法
调用了 ApplicationContextAware 的 setApplicationContext 方法
beanName:myAware
是否为单例:true

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-3.0.xsd">
<bean id="myAware" class="com.learn.initbean.MyAware">
</bean>
</beans>

总结

实际上可以看出来,Aware 接口的 set 方法,就是通过 #getBean(...) 方法调用时执行的。Spring 容器在初始化主动检测当前 bean 是否实现了 Aware 接口,如果实现了则回调其 set 方法将相应的参数设置给该 bean ,这个时候该 bean 就从 Spring 容器中取得相应的资源。

接口实现类的列表

  • LoadTimeWeaverAware:加载Spring Bean时织入第三方模块,如AspectJ
  • BeanClassLoaderAware:加载Spring Bean的类加载器
  • BootstrapContextAware:资源适配器BootstrapContext,如JCA,CCI
  • ResourceLoaderAware:底层访问资源的加载器
  • BeanFactoryAware:声明BeanFactory
  • PortletConfigAware:PortletConfig
  • PortletContextAware:PortletContext
  • ServletConfigAware:ServletConfig
  • ServletContextAware:ServletContext
  • MessageSourceAware:国际化
  • ApplicationEventPublisherAware:应用事件
  • NotificationPublisherAware:JMX通知
  • BeanNameAware:声明Spring Bean的名字

demo地址

https://gitee.com/daifylearn/springLearn

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大·风

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值