BeanPostProcessor,bean,Aware,ApplicationContextAware RequestContextHolder

 

 

 HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
 String token = request.getHeader("");

@Autowired
protected HttpServletRequest request;

 

SuperScheduledPostProcessor implements BeanPostProcessor, ApplicationContextAware {
BeanPostProcessor该接口我们也叫后置处理器,作用是在Bean对象在实例化和依赖注入完毕后,在初始化方法的前后添加我们自己的逻辑
通过 BeanPostProcessor 解析Scheduled注解,收集指定注解的类、方法名


implements ApplicationRunner, ApplicationContextAware {
ApplicationRunner springBoot项目启动时候,有时候需要再启动之后直接执行某一段代码。这个时候就用到了 ApplicationRunner 这个类
@Override
public void run(ApplicationArguments args) {


SuperScheduledManager.addScheduled
threadPoolTaskScheduler.schedule(runnable, new CronTrigger(scheduledSource.getCron()));

@EnablexxxJmsMqListener 注解中引入 @Import(ImportxxxJsmListenerBeanDefinition.class)
ImportxxxJsmListenerBeanDefinition implements ImportBeanDefinitionRegistrar, EnvironmentAware {//获取注解依次处理

 

public class SuperScheduledPostProcessor implements BeanPostProcessor, ApplicationContextAware {

    ApplicationContext applicationContext;
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

        Method[] methods = bean.getClass().getDeclaredMethods();
        MyTestService myTestService;
         //循环处理对每个方法逐一处理
        if (methods.length > 0) {
            for (Method method : methods) {
                //3.尝试在该方法上获取@Scheduled注解(SpringBoot的定时任务注解)
                ProcessTest annotation = method.getAnnotation(ProcessTest.class);
                //如果无法获取到@Scheduled注解,就跳过这个方法
                if (annotation == null) {
                    continue;
                }
                System.out.println(beanName+" "+method.getName()+" "+annotation.value());
                myTestService = (MyTestService) this.applicationContext.getBean("myTestService");
                if(myTestService.getMap() == null){
                    myTestService.setMap(new HashMap());
                }
                myTestService.getMap().put(beanName,method.getName()+":"+annotation.value());
            }
        }

        return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
    }
}

@Configuration
@Import(SuperScheduledPostProcessor.class)// 等同于注册实例到容器
public class ConfigTest {

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ProcessTest {
    String value();
}

@Service
public class MyTestService {
    private Map map ;

    public Map getMap() {
        return map;
    }

    public void setMap(Map map) {
        this.map = map;
    }
}
@Service
public class MyTestMain {
    @ProcessTest("mytestMainValue")
    public void mytestMainMethod(){
    }
}
@Service
public class MyTest {
    public String s ="s";

    @ProcessTest("myTestValue")
    public void myTestMethod(){

    }
}

测试
    @Autowired
    MyTestService myTestService;
    @RequestMapping("/hello")
    @ResponseBody
    public String hello() {
        System.out.println("***************hello1:"+myTestService.getMap());
        return "hello:";
    }

BeanNameAware 获得到容器中Bean的名称
BeanFactoryAware 获得当前bean Factory,从而调用容器的服务
ApplicationContextAware 当前的application context从而调用容器的服务
MessageSourceAware 得到message source从而得到文本信息
ApplicationEventPublisherAware 应用时间发布器,用于发布事件
ResourceLoaderAware 获取资源加载器,可以获得外部资源文件

public class SuperScheduledApplicationRunnerMy implements ApplicationRunner{
    @Override
    public void run(ApplicationArguments args) {
       //服务启动后需要执行的代码

这个接口表面上的作用就是让实现这个接口的bean知道自己在spring容器里的名字,而且听官方的意思是这个接口更多的使用在spring的框架代码中,实际开发环境应该不建议使用,因为spring认为bean的名字与bean的联系并不是很深

@Service
public class BeanNameAwareTest implements BeanNameAware {
    @Override
    public void setBeanName(String s) {
        System.out.println("BeanNameAwareTest************"+s);
    }
}
 
@Service
public class BeanFactoryAwareTest implements BeanFactoryAware {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        MyTestService myTestService = beanFactory.getBean(MyTestService.class);
        myTestService.myService();
    }
}
 
@Service
public final class SettingsBean implements ResourceLoaderAware {
    private static Properties settings;
    private ResourceLoader loader;
    private static final String SETTINGS_FILE = "classpath:/config/settings.properties";
     
    @Override
    public void setResourceLoader(ResourceLoader loader) {
        this.loader = loader;
        try {
            FileInputStream inputStream = new FileInputStream(loader.getResource(SETTINGS_FILE).getFile());
            settings = new Properties();
            settings.load(inputStream);
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    public void save() {
        try {
            OutputStream outputStream = new FileOutputStream(loader.getResource(SETTINGS_FILE).getFile());
            settings.store(outputStream, "");
            outputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
 
    public Properties getSettings() {
        return settings;
    }
    public void setProperty(String key, String value) {
        settings.setProperty(key, value);
 
    }
    public static String getProperty(String key) {
        return settings.getProperty(key);
    }
 
    public double getDouble(String key) {
        return Double.parseDouble(settings.getProperty(key));
    }
 
    public int getInteger(String key) {
        return Integer.parseInt(settings.getProperty(key));
    }
}

 

@Configuration
public class ConfigTest {
    @Bean
    public MyTest myTestsssss(){//生产myTestsssss实例id
        return new MyTest();
    }

    @Bean
    public MyTestMain myTestMainxxxx(MyTest myTestsssss){
        System.out.println("*********************myTestsssss:"+myTestsssss+","+myTestsssss.s);
        System.out.println("*********************myTestsssss():"+myTestsssss());
        return new MyTestMain();
    }

    @Bean
    public ResultVo resultVo(){
        System.out.println("*********************");
        myTestMainxxxx(new MyTest());
        return null;
    }

实例化完成后,不会重复实例化
*********************myTestsssss:cn.com.domain.MyTest@18eec010,s
*********************myTestsssss():cn.com.domain.MyTest@18eec010
*********************

  

java的注解实现的核心技术是反射,让我们通过一些例子以及自己实现一个注解来理解它工作的原理

@Override注解使用java官方提供的注解,它的定义里面并没有任何的实现逻辑。注意,所有的注解几乎都是这样的,注解只能是被看作元数据,它不包含任何业务逻辑。 注解更像是一个标签,一个声明,表面被注释的这个地方,将具有某种特定的逻辑,那么注解的功能是如何实现的呢?答案必然是别的某个地方对这个注解做了实现。以@Override注解为例,他的功能是重写一个方法,而他的实现者就是JVM,java虚拟机,java虚拟机在字节码层面实现了这个功能

我们自己想定义一个独一无二的注解的话,则我们需要自己为注解写一个实现逻辑,换言之,我们需要实现自己注解特定逻辑的功能。

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface SimpleAnnotation {
String value();
}
它的目标注释对象是方法,保留策略是在运行期间。

在Spring的众多注解中,经常会发现很多注解的不同属性起着相同的作用,比如@RequestMapping的value属性和path属性,这就需要做一些基本的限制,比如value和path的值不能冲突,比如任意设置value或者设置path属性的值,都能够通过另一个属性来获取值等等。为了统一处理这些情况,Spring创建了@AliasFor标签。

 

 

 

 

 

 

 

 

 

 

posted @ 2021-07-11 21:02  XUMT111  阅读(114)  评论(0编辑  收藏  举报