SpringBoot整合自定义注解
之前我们学习了java的自定义注解,而且我们可以非常方便的进行注解值到实体真实值得转变。那么我们如何将这些标记值设置到spring容器中?那么我们就需要了解一些spring的知识。我们知道spring提供了很多扩展的接口。这其中有一个BeanPostProcessor的接口。
话不多说,直接上代码
public class MyBeanPostProcessor implements BeanPostProcessor {
//在bean实例化之后调用
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
//在bean实例化之后调用
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
try {
parseAnnotation(bean);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return bean;
}
//在bean实例化之后进行参数赋值,处理完毕之后,spring容器中的bean就是注解中的值了。
public void parseAnnotation(Object bean) throws IllegalAccessException {
//获取公有和私有的属性
Field[] fields = bean.getClass().getDeclaredFields();
for (int i=0;i<fields.length;i++){
//抑制对private的检测
fields[i].setAccessible(true);
Object value=fields[i].get(bean);
MyField myField=fields[i].getAnnotation(MyField.class);
//如果默认传入的是空的
if (null!=myField&& StringUtils.isEmpty(value)){
fields[i].set(bean,myField.myName());
}
}
}
}
@SpringBootApplication
public class tet implements ApplicationContextAware {
@Bean(initMethod = "initSon")
public Son son(){
return new Son();
}
//不能采用其他注解修饰拥有BeanPostProcessor接口,只能用@Bean。
@Bean
public MyBeanPostProcessor getMybean(){
return new MyBeanPostProcessor();
}
private static Son son;
private static ApplicationContext context;
public static void main(String[] args) {
SpringApplication.run(tet.class, args);
son= context.getBean(Son.class);
System.out.println("新的:"+son.toString());
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.context=applicationContext;
}
}
我们看到我们已经拿到注解的值并修改了spring容器中bean的值了。同样的道理,我们也可以通过bean来遍历方法,然后拿到方法上的注解属性。但是使用方法上的注解的时候都是AOP来兼容代码。也就是说在切面里接受注解上边的属性。这个咋后期再研讨。现在咋没爬一爬代码,看看刚才的BeanPostProcessor是如何调用的。
首先我们看到BeanPostProcessor的两个接口。前置和后置的处理器。通过上边的例子,我们知道如果我们什么多不做,那么return bean就应该注册到Spring的容器中了。
public interface BeanPostProcessor {
//在bean实例化之后调用
default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
//在bean实例化之后调用
default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
}
通过代码跟踪,在initalizeBean中
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged((PrivilegedAction<Object>) () -> {
//执行aware接口
invokeAwareMethods(beanName, bean);
return null;
}, getAccessControlContext());
}
else {
//aware接口
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
//beanPostProcessors的前置接口
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
//intit接口
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()) {
//beanPostProcessors的前置接口
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
可以看出方法执行的顺序为
invokeAwareMethods->
applyBeanPostProcessorsBeforeInitialization->
invokeInitMethods->
applyBeanPostProcessorsAfterInitialization
调用的aware接口方法
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);
}
}
}
调用的BeanPostProcessors接口方法
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessBeforeInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
throws BeansException {
Object result = existingBean;
for (BeanPostProcessor processor : getBeanPostProcessors()) {
Object current = processor.postProcessAfterInitialization(result, beanName);
if (current == null) {
return result;
}
result = current;
}
return result;
}
调用的InitializingBean接口方法
protected void invokeInitMethods(String beanName, final Object bean, @Nullable RootBeanDefinition mbd)
throws Throwable {
boolean isInitializingBean = (bean instanceof InitializingBean);
if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
if (logger.isTraceEnabled()) {
logger.trace("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
}
if (System.getSecurityManager() != null) {
try {
AccessController.doPrivileged((PrivilegedExceptionAction<Object>) () -> {
((InitializingBean) bean).afterPropertiesSet();
return null;
}, getAccessControlContext());
}
catch (PrivilegedActionException pae) {
throw pae.getException();
}
}
else {
((InitializingBean) bean).afterPropertiesSet();
}
}
所以接口的执行顺序为aware->beanpostprocess->InitializingBean->beanpostprocess
而我们的getBeanPostProcessors()就是用来获取所有实现了beanpostprocessors接口的类。那么这些类是如何放到beanfactory里的呐?
我们返爬一下代码,在beanfactory中。发现
@Override
public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
Assert.notNull(beanPostProcessor, "BeanPostProcessor must not be null");
// Remove from old position, if any
this.beanPostProcessors.remove(beanPostProcessor);
// Track whether it is instantiation/destruction aware
if (beanPostProcessor instanceof InstantiationAwareBeanPostProcessor) {
this.hasInstantiationAwareBeanPostProcessors = true;
}
if (beanPostProcessor instanceof DestructionAwareBeanPostProcessor) {
this.hasDestructionAwareBeanPostProcessors = true;
}
// Add to end of list
this.beanPostProcessors.add(beanPostProcessor);
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
{
int factoryId = System.identityHashCode(beanFactory);
if (this.factoriesPostProcessed.contains(factoryId)) {
throw new IllegalStateException(
"postProcessBeanFactory already called on this post-processor against " + beanFactory);
}
this.factoriesPostProcessed.add(factoryId);
if (!this.registriesPostProcessed.contains(factoryId)) {
// BeanDefinitionRegistryPostProcessor hook apparently not supported...
// Simply call processConfigurationClasses lazily at this point then.
processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);
}
enhanceConfigurationClasses(beanFactory);
beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));
}
我们继续向调用者跟踪,发现了核心代码。就这这个registerBeanPostProcessors方法中。
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
//通过beanfactory获取实现了beanPostProcessor接口的类的名称。
String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);
//实现了beanPostProcessor接口的类数量
int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
//做了
beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
//具有优先级的
List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
//实现ordered接口的
List<String> orderedPostProcessorNames = new ArrayList<>();
//一般的
List<String> nonOrderedPostProcessorNames = new ArrayList<>();
for (String ppName : postProcessorNames) {
if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
//优先级接口
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
priorityOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
//如实现Orderd接口
orderedPostProcessorNames.add(ppName);
}
else {
nonOrderedPostProcessorNames.add(ppName);
}
}
sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
//注册优先级的beanpostprocessors
registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
for (String ppName : orderedPostProcessorNames) {
//进行实例化
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
orderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
sortPostProcessors(orderedPostProcessors, beanFactory);
//注册ordered的beanpostprocessors
registerBeanPostProcessors(beanFactory, orderedPostProcessors);
//一般的beanpostprocessors
List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
for (String ppName : nonOrderedPostProcessorNames) {
BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
nonOrderedPostProcessors.add(pp);
if (pp instanceof MergedBeanDefinitionPostProcessor) {
internalPostProcessors.add(pp);
}
}
//注册一般的beanpostprocessors
registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
//排序
sortPostProcessors(internalPostProcessors, beanFactory);
registerBeanPostProcessors(beanFactory, internalPostProcessors);
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}
这里的getbean就是spring的实例化bean的过程。也就是registerBeanPostProcessors方法之后,实现BeanPostProcessors接口的类都已经实例化好了。
我们再向前走一步。
而其中的onRefresh方法是spring留给子类进行bean的初始化的。而且该方法也添加了synchronized锁,而beanPostProcessors类在其他bean初始化之前已经初始化了。所以根据上边的解释。bean初始化结束之后肯定会调用postProcessAfterInitialization,而不存在beanPostProcessors类还没有初始化的问题,就被其他类调用的问题。
- ASP.NET AJAX(6)__Microsoft AJAX Library中的面向对象类型系统命名空间类类——构造函数类——定义方法类——定义属性类——注册类类——抽象类类——继承类——调用父类方
- 设计模式专题(四)——代理模式
- Array数组函数(一)
- ASP.NET AJAX(5)__JavaScript原生类型以及Microsoft AJAX Library什么是Microsoft AJAX LibraryObject原生类型Object.pro
- 使用 Octave 来学习 Machine Learning(一)
- ASP.NET AJAX(4)__客户端访问WebService服务器端释放WebService方法客户端访问WebService客户端访问PageMethod错误处理复杂数据类型使用基础客户端代理的
- 讲真,你该做备份的有效性校验了
- memcache安装方法
- 设计模式专题(五)——工厂方法模式
- ASP.NET AJAX(11)__ScriptManagerUpdatePanel的支持成员功能控制成员脚本控件支持成员ScriptMode和ScriptPathLoadScriptsBeforeU
- SQL Server 2016新特性:动态数据屏蔽(DDM)
- ASP.NET AJAX(12)__浏览器兼容功能判断浏览器的类型和版本Sys.Browser针对DOM元素的兼容操作针对DOM事件的兼容操作
- 设计模式专题(六)——原型模式
- ASP.NET AJAX(13)__利用Microsoft AJAX Library开发客户端组件Sys.Component成员Sys.IDisposable成员Sys.INotifyDisposin
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- 应该在JavaScript中使用Class吗
- Go语言小书 | 关于编译和语法
- Go语言小书 | 小试牛刀,从hello world开始
- 3分钟短文 | Laravel 中间件传递数据到控制器
- 3分钟短文 | Laravel 表单验证数组的数据
- 3分钟短文:Laravel 编程中优雅地添加定义常量
- 极客算法训练笔记(四),栈和队列,从实际应用看数据结构
- 微博爬虫出错居然还和网络运营商有关
- 8.深入k8s:资源控制Qos和eviction及其源码分析
- 1. 不吹不擂,第一篇就能提升你对Bean Validation数据校验的认知
- CNN不用乘法? AdderNet和DeepShift论文理解
- 动手构建地铁关系网,实现最短路径查询
- Java并发编程(08):Executor线程池框架
- 用Scipy求解单个正态总体的置信区间
- 架构设计 | 基于电商交易流程,图解TCC事务分段提交