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标签。

浙公网安备 33010602011771号