Skip to content

7. BeanPostProcessor

yuzd edited this page Jul 18, 2021 · 2 revisions

BeanPostProcessor的设计

参考Spring框架, 在类的初始化过程中进行自定义逻辑而设计的BeanPostProcessor,有2个方法:

  • PostProcessBeforeInitialization
  • PostProcessAfterInitialization

1. PostProcessBeforeInitialization

该方法在bean实例化完毕(且已经注入完毕),属性设置或自定义init方法执行之前执行!

2. PostProcessAfterInitialization

该方法在bean实例化完毕(且已经注入完毕),在属性设置或自定义init方法执行之后

一个使用场景例子:自定义一个注解来封装自定义逻辑

先定义一个自定义注解

/// <summary>
/// 測試自己實現一個自定義註解
/// </summary>
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
public sealed class Soa : Attribute
{
    /// <summary>
    /// 构造函数
    /// </summary>
    public Soa(Type type)
    {
        Type = type;
    }

    /// <summary>
    /// 注册的类型
    /// </summary>
    internal Type Type { get; set; }
}

这个注解的名字叫Soa,然后有一个构造方法,传参为一个Class Type

下面需要实现一个BeanPostProcessor

[Component]
public class SoaProcessor : BeanPostProcessor
{
    //在实例化后且属性设值之前执行
    public object PostProcessBeforeInitialization(object bean)
    {
        
        Type type = bean.GetType();
        ////找到bean下所有的字段
        var fieldInfos = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
        foreach (var field in fieldInfos)
        {
            //看字段上面有没有打Soa自定义注解
            var soaAnnotation = field.GetCustomAttribute(typeof(Soa)) as Soa;
            if (soaAnnotation == null)
            {
                continue;
            }
            //有的话根据注解的参数Type来实例化对象并设值
            var instance = Activator.CreateInstance(soaAnnotation.Type) as ISoa;
            if (instance == null)
            {
                continue;
            }

            field.SetValue(bean, instance);
        }

        return bean;
    }

    //不管返回
    public object PostProcessAfterInitialization(object bean)
    {
        return bean;
    }
}

好了,实现一个BeanPostProcessor就是写一个类继承并实现它的接口即可。 然后打上[Compoment]注册到容器中即可。

下面测试效果

[Component]
public class Test11Models1
{
    [Soa(typeof(SoaTest1))] 
    private ISoa Soa1;

    [Soa(typeof(SoaTest2))] 
    private ISoa Soa2;

    public string getSoa1()
    {
        return Soa1.say();
    }

    public string getSoa2()
    {
        return Soa2.say();
    }
}

public interface ISoa
{
    string say();
}

public class SoaTest1 : ISoa
{
    public string say()
    {
        return nameof(SoaTest1);
    }
}

public class SoaTest2 : ISoa
{
    public string say()
    {
        return nameof(SoaTest2);
    }
}

单元测试一下

[Fact]
public void Test1()
{
    var builder = new ContainerBuilder();
    builder.RegisterSpring(r => r.RegisterAssembly(typeof(TestBeanPostProcessor).Assembly));
    var container = builder.Build();
    var isRegisterd = container.TryResolve(out Test11Models1 model1);
    Assert.True(isRegisterd);
    Assert.Equal("SoaTest1",model1.getSoa1());
    Assert.Equal("SoaTest2",model1.getSoa2());
}

Test11Models1这个类打了[Compoment]注册到容器,当从容器获取它的时候会走到上面的SoaProcessor。然后识别到里面有打了自定义注解[Soa],并根据注册的参数实例化。