1.实现了BeanPostProcessor接口,可先看这个接口 ApplicationContext可以在自动检测BeanPostProcessor bean,在它创建完后可以创建任何的bean。

public interface BeanPostProcessor {
/*可以在bean实例化之前调用这个方法,类似init-method,
*这个方法可以对bean进行操作
*/
Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException; /**可以在bean实例化之后调用这个方法,类似init-method,
*这个方法可以对bean进行操作
*/
Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
}

简单实现自己的一个Processor

public class MyBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor before->"+beanName);
return bean;
} @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("MyBeanPostProcessor after -> "+beanName);
return bean;
}
}

spring-beans.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" xmlns:mvc="http://www.springframework.org/schema/mvc"
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/mvc
http://www.springframework.org/schema/mvc/spring-mvc.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="student" class="org.lzyer.test.Student"></bean>
<bean class="org.lzyer.test.MyBeanPostProcessor"/>
</beans>

测试类

@Test
public void testMyProcessor(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("spring/spring-beans.xml");
Student student = (Student) ctx.getBean("student");
System.out.println(student); }

运行结果:

MyBeanPostProcessor before->student
MyBeanPostProcessor after -> student
org.lzyer.test.Student@4d826d77

2.AutowiredAnnotationBeanPostProcessor
BeanPostProcessor的实现类,实现了自动注入属性、方法,可以使用jdk5的注解,默认使用spring的@Autowried和@Value注解。可以在spring配置文件中添加context:annotation-config和context:component-scan来注入AutowiredAnnotationBeanPostProcessor,另外注解的注入在xml配置文件注入之前。

3.spring在哪里注入了BeanPostProcessor

spring容器调用refresh方法中的

// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
   /**
* Instantiate and invoke all registered BeanPostProcessor beans,
* respecting explicit order if given.
* <p>Must be called before any instantiation of application beans.
实例化并注入所有BeanPostProcessor,必须在bean实例化之前调用。
*/
protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
PostProcessorRegistrationDelegate.registerBeanPostProcessors(beanFactory, this);
}

4.回归到AutowiredAnnotationBeanPostProcessor
构造方法

public AutowiredAnnotationBeanPostProcessor() {
this.autowiredAnnotationTypes.add(Autowired.class);
this.autowiredAnnotationTypes.add(Value.class);
try {
this.autowiredAnnotationTypes.add((Class<? extends Annotation>)
ClassUtils.forName("javax.inject.Inject", AutowiredAnnotationBeanPostProcessor.class.getClassLoader()));
logger.info("JSR-330 'javax.inject.Inject' annotation found and supported for autowiring");
}
catch (ClassNotFoundException ex) {
// JSR-330 API not available - simply skip.
}
}

构造方法中初始化注解的类型是@Autowried,@Value以及Annotation的子类
里面包含2个内部类AutowiredFieldElement和AutowiredMethodElement分别处理字段和方法的注解。

先看AutowiredFieldElement中inject方法

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
Field field = (Field) this.member;
try {
Object value;
if (this.cached) {//属性有缓存
value = resolvedCachedArgument(beanName, this.cachedFieldValue);
}
else {
DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
desc.setContainingClass(bean.getClass());
Set<String> autowiredBeanNames = new LinkedHashSet<String>(1);
TypeConverter typeConverter = beanFactory.getTypeConverter();
value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
synchronized (this) {
if (!this.cached) {//没有缓存
if (value != null || this.required) {
this.cachedFieldValue = desc;
registerDependentBeans(beanName, autowiredBeanNames);//注入依赖
if (autowiredBeanNames.size() == 1) {
String autowiredBeanName = autowiredBeanNames.iterator().next();
if (beanFactory.containsBean(autowiredBeanName)) {
//对字段进行类型匹配
if (beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
this.cachedFieldValue = new RuntimeBeanReference(autowiredBeanName);
}
}
}
}
else {
this.cachedFieldValue = null;
}
this.cached = true;
}
}
}
if (value != null) {
ReflectionUtils.makeAccessible(field);
field.set(bean, value);//反射注入值
}
}
catch (Throwable ex) {
throw new BeanCreationException("Could not autowire field: " + field, ex);
}
}
}

AutowiredMethodElement的inject方法

protected void inject(Object bean, String beanName, PropertyValues pvs) throws Throwable {
if (checkPropertySkipping(pvs)) {
return;
}
Method method = (Method) this.member;
try {
Object[] arguments;
if (this.cached) {//缓存方法参数
// Shortcut for avoiding synchronization...
arguments = resolveCachedArguments(beanName);
}
else {
//获取方法的所有参数
Class<?>[] paramTypes = method.getParameterTypes();
arguments = new Object[paramTypes.length];
DependencyDescriptor[] descriptors = new DependencyDescriptor[paramTypes.length];
Set<String> autowiredBeanNames = new LinkedHashSet<String>(paramTypes.length);
TypeConverter typeConverter = beanFactory.getTypeConverter();
//参数处理
for (int i = 0; i < arguments.length; i++) {
MethodParameter methodParam = new MethodParameter(method, i);
DependencyDescriptor desc = new DependencyDescriptor(methodParam, this.required);
desc.setContainingClass(bean.getClass());
descriptors[i] = desc;
Object arg = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
if (arg == null && !this.required) {
arguments = null;
break;
}
arguments[i] = arg;
}
synchronized (this) {
if (!this.cached) {
if (arguments != null) {
this.cachedMethodArguments = new Object[arguments.length];
for (int i = 0; i < arguments.length; i++) {
this.cachedMethodArguments[i] = descriptors[i];
}
registerDependentBeans(beanName, autowiredBeanNames);
if (autowiredBeanNames.size() == paramTypes.length) {
Iterator<String> it = autowiredBeanNames.iterator();
for (int i = 0; i < paramTypes.length; i++) {
String autowiredBeanName = it.next();
if (beanFactory.containsBean(autowiredBeanName)) {
if (beanFactory.isTypeMatch(autowiredBeanName, paramTypes[i])) {
this.cachedMethodArguments[i] = new RuntimeBeanReference(autowiredBeanName);
}
}
}
}
}
else {
this.cachedMethodArguments = null;
}
this.cached = true;
}
}
}
if (arguments != null) {
ReflectionUtils.makeAccessible(method);
method.invoke(bean, arguments);//反射调用方法
}
}
catch (InvocationTargetException ex) {
throw ex.getTargetException();
}
catch (Throwable ex) {
throw new BeanCreationException("Could not autowire method: " + method, ex);
}
}

查找注解

private AnnotationAttributes findAutowiredAnnotation(AccessibleObject ao) {
for (Class<? extends Annotation> type : this.autowiredAnnotationTypes) {
AnnotationAttributes ann = AnnotatedElementUtils.getAnnotationAttributes(ao, type.getName());
if (ann != null) {
return ann;
}
}
return null;
}

Spring源码解析-AutowiredAnnotationBeanPostProcessor的更多相关文章

  1. Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean

    Spring源码解析之八finishBeanFactoryInitialization方法即初始化单例bean 七千字长文深刻解读,Spirng中是如何初始化单例bean的,和面试中最常问的Sprin ...

  2. Spring源码解析 - AbstractBeanFactory 实现接口与父类分析

    我们先来看类图吧: 除了BeanFactory这一支的接口,AbstractBeanFactory主要实现了AliasRegistry和SingletonBeanRegistry接口. 这边主要提供了 ...

  3. spring 源码解析

    1. [文件] spring源码.txt ~ 15B     下载(167) ? 1 springн┤┬вио╬Ш: 2. [文件] spring源码分析之AOP.txt ~ 15KB     下载( ...

  4. Spring源码解析——循环依赖的解决方案

    一.前言 承接<Spring源码解析--创建bean>.<Spring源码解析--创建bean的实例>,我们今天接着聊聊,循环依赖的解决方案,即创建bean的ObjectFac ...

  5. Spring源码解析-ioc容器的设计

    Spring源码解析-ioc容器的设计 1 IoC容器系列的设计:BeanFactory和ApplicatioContext 在Spring容器中,主要分为两个主要的容器系列,一个是实现BeanFac ...

  6. Spring源码解析系列汇总

    相信我,你会收藏这篇文章的 本篇文章是这段时间撸出来的Spring源码解析系列文章的汇总,总共包含以下专题.喜欢的同学可以收藏起来以备不时之需 SpringIOC源码解析(上) 本篇文章搭建了IOC源 ...

  7. Spring源码解析之PropertyPlaceholderHelper(占位符解析器)

    Spring源码解析之PropertyPlaceholderHelper(占位符解析器) https://blog.csdn.net/weixin_39471249/article/details/7 ...

  8. Spring源码解析之BeanFactoryPostProcessor(三)

    在上一章中笔者介绍了refresh()的<1>处是如何获取beanFactory对象,下面我们要来学习refresh()方法的<2>处是如何调用invokeBeanFactor ...

  9. Spring源码解析之ConfigurationClassPostProcessor(二)

    上一个章节,笔者向大家介绍了spring是如何来过滤配置类的,下面我们来看看在过滤出配置类后,spring是如何来解析配置类的.首先过滤出来的配置类会存放在configCandidates列表, 在代 ...

随机推荐

  1. 08 datetime与logging模块(进阶)

    datetime与logging模块 阶段一:日期与时间 1.datetime 模块中 主要类: 类名 功能说明 date 日期对象,常用的属性有year, month, day time 时间对象h ...

  2. semcms 网站漏洞挖掘过程与安全修复防范

    emcms是国内第一个开源外贸的网站管理系统,目前大多数的外贸网站都是用的semcms系统,该系统兼容许多浏览器,像IE,google,360极速浏览器都能非常好的兼容,官方semcms有php版本, ...

  3. Python3爬虫(十二) 爬虫性能

    Infi-chu: http://www.cnblogs.com/Infi-chu/ 一.简单的循环串行一个一个循环,耗时是最长的,是所有的时间综合 import requests url_list ...

  4. 利用nodejs实现商品管理系统(一)

    一.界面分类:用户登录界面,商品管理界面(包含商品编辑,创建,删除,列表界面) 功能实现:1.用户输入用户名与密码,通过加密,与数据库校验,如果正确,则跳转到商品管理界面,否则一直停留在用户界面. 2 ...

  5. Sql Server 表间对应关系

    <1>.关联映射:一对多/多对一 存在最普遍的映射关系,简单来讲就如球员与球队的关系:一对多:从球队角度来说一个球队拥有多个球员 即为一对多多对一:从球员角度来说多个球员属于一个球队 即为 ...

  6. windows下subversion服务器搭建

    一.下载subversion服务器端和客户端软件 1.subversion下载地址:http://subversion.tigris.org/ 2.svn比较流行的客户端Tortoisesvn下载地址 ...

  7. 介绍PHP的自动加载

    昨天面试被问到了 PHP 的自动加载机制,因为很多概念模糊啦,没回答好,今天特意来总结一下. include 和 require 是PHP中引入文件的两个基本方法,但是每个脚本的开头,都需要包含(in ...

  8. 【Keras案例学习】 多层感知机做手写字符分类(mnist_mlp )

    from __future__ import print_function # 导入numpy库, numpy是一个常用的科学计算库,优化矩阵的运算 import numpy as np np.ran ...

  9. spring boot 连接mysql 错误The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more than one

    1.spring boot 整合mybatis 连接mysql时错误 The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or repr ...

  10. 剑指offer-矩形覆盖10

    题目描述 我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形.请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? # -*- coding:utf-8 -*- class S ...