SpringBoot获取自定义注解属性-类-方法
写了个自定义注解,想获取自定义注解的属性,或者标在方法上的注解上的属性
获取自定义注解在类上的属性值
//获取自定义注解的配置的所有bean
final Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(EnableRetryRabbitMq.class);
for (String key : beansWithAnnotation.keySet()) {
String scanPackage = "com.pkk";
//获取指定bean的注解为EnableRetryRabbitMq.class的注解属性
final EnableRetryRabbitMq annotation = AnnotationUtils.findAnnotation(beansWithAnnotation.get(key).getClass(), EnableRetryRabbitMq.class);
if (null != annotation && StringUtils.isNotBlank(annotation.scanBasePackages())) {
scanPackage = annotation.scanBasePackages();
}
//注入bean(自己封装的方法,详情看下面)
RetrySpringUtil.handleRegisterBeanWithSpringToInitConfigurerationBean(applicationContext);
}
-- 说明
①:applicationContext是ApplicationContent,可以通过实现ApplicationContextAware来获取
获取自定义注解在方法上的属性值
**
* @Description: 处理并注册bean
* @Param: [applicationContext, scanPackage]
* @return: void
* @Author: pkk
* @Date: 2019/9/6 0006 下午 1:35
*/
public static void handleRegisterBeanWithSpringToInitConfigurerationBean(ApplicationContext applicationContext) {
//获取自定义注解的配置
final Map<String, Object> beansWithAnnotation = applicationContext.getBeansWithAnnotation(InitRetryRabbitMq.class);
for (String key : beansWithAnnotation.keySet()) {
//Spring 代理类导致Method无法获取,这里使用AopUtils.getTargetClass()方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(AopUtils.getTargetClass(beansWithAnnotation.get(key).getClass()));
for (Method method : methods) {
//获取指定方法上的注解的属性
final InitRetryRabbitMq initRetryRabbitMq = AnnotationUtils.findAnnotation(method, InitRetryRabbitMq.class);
if (null != initRetryRabbitMq) {
//验证必要的注解的属性
String queueName = Optional.ofNullable(initRetryRabbitMq.queueName()).orElseThrow(() -> new IllegalArgumentException("Please specify the queue name of the queue!"));
//多个bean的时候相当于起个别名
String registerBean = queueName + "InitConfigurerationBean";
//将bean注册到Spring容器中,通过构造函数的方式进行注入
SpringRegisterBean.registerBean((ConfigurableApplicationContext) applicationContext, registerBean, InitConfigurerationBean.class, initRetryRabbitMq, applicationContext);
log.info("The registration bean is " + registerBean + ",Configuration information is " + JSONObject.toJSONString(initRetryRabbitMq));
}
}
}
}
将bean手动注入到Spring中
采用BeanDefinitionBuilder(bean定义构造器)使用构造函数的方式注入bean
/**
* 主动向Spring容器中注册bean
*
* @param applicationContext Spring容器
* @param beanName BeanName
* @param registerBeanClazz 将要注册的bean的类
* @param args 构造方法的必要参数,顺序和类型要求和clazz中定义的一致
* @return 返回注册到容器中的bean对象
*/
public static <T> T registerBean(ConfigurableApplicationContext applicationContext, String beanName, Class<T> registerBeanClazz,
Object... args) {
//容器中是否已经包含此bean
if (applicationContext.containsBean(beanName)) {
Object bean = applicationContext.getBean(beanName);
//的类或接口是否相同,或是否是其超类或超接口。如果是则返回 true;否则返回 false。如果该 Class 表示一个基本类型,且指定的 Class 参数正是该 Class 对象,则该方法返回 true;否则返回 false
if (bean.getClass().isAssignableFrom(registerBeanClazz)) {
return (T) bean;
} else {
throw new RuntimeException("BeanName 重复 " + beanName);
}
}
//Spring的bean的定义构造器
BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(registerBeanClazz);
//给要注册的bean设置构造函数相应的参数,注意,顺序要相同
for (Object arg : args) {
beanDefinitionBuilder.addConstructorArgValue(arg);
}
//获取原始的bean
BeanDefinition beanDefinition = beanDefinitionBuilder.getRawBeanDefinition();
//获取bean定义注册的工厂
BeanDefinitionRegistry beanFactory = (BeanDefinitionRegistry) applicationContext.getBeanFactory();
//开启注册bean到Sring容器中
beanFactory.registerBeanDefinition(beanName, beanDefinition);
return applicationContext.getBean(beanName, registerBeanClazz);
}
bean的初始化操作
package com.pkk.log.web.configure;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
/**
* @description: bean创建之后的操作, 会调用postProcessAfterInitialization
* @author: peikunkun
* @create: 2019-09-04 17:19
**/
@Slf4j
@Component
public class BeanCreateProcessor implements BeanPostProcessor {
/**
* @Description: bean初始化之前的曹组
* @Param: [bean, beanName]
* @return: java.lang.Object
* @Author: peikunkun
* @Date: 2019/9/6 0006 下午 3:10
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
log.info("bean ->" + beanName + "初始化之前的操作");
return bean;
}
/**
* @Description: bean创建之后的操作
* @Param: [bean, beanName]
* @return: java.lang.Object
* @Author: peikunkun
* @Date: 2019/9/4 0004 下午 5:42
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
log.info("bean ->" + beanName + "初始化之后的操作");
return bean;
}
}
@Slf4j
@Component
class InitializingBeanTest implements InitializingBean {
public void init() {
System.out.println("init-method is called");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("afterPropertiesSet-method is called");
}
}
class mainTest {
public static void main(String[] args) {
System.out.println("执行顺序:\n" +
"afterPropertiesSet 和init-method之间的执行顺序是afterPropertiesSet 先执行,init-method 后执行。\n" +
"从BeanPostProcessor的作用,可以看出最先执行的是postProcessBeforeInitialization,然后是afterPropertiesSet,"
+ "然后是init-method,然后是postProcessAfterInitialization。");
}
}