Spring07- Spring高级特性


环境说明

  • JDK 17
  • Spring 6.0.6

环境准备

添加 Spring 依赖:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>6.0.6</version>
</dependency>

Bean Aware

Spring提供了一些以Aware结尾的接口,实现了Aware接口的bean在被初始化之后,可以获取相应资源。即实现了Aware接口的类会获得某些感知能力,Spring容器会在Bean被加载时,根据类实现的感知接口,调用类中实现的对应感知方法。

比如 BeanNameAware 接口,这个接口获取的资源就是BeanName:

@Component
public class Student implementsBeanNameAware {

    public void study(){
        System.out.println("室友还在打游戏,我狠狠的学Java,太爽了");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("我在加载阶段获取了Bean 的名字 " + name);
    }
}

又比如BeanClassLoaderAware,它能够使得我们在Bean加载阶段就获取到当前Bean的类加载器:

@Component
public class Student implements BeanClassLoaderAware{

    public void study(){
        System.out.println("室友还在打游戏,我狠狠的学Java,太爽了");
    }

    @Override
    public void setBeanClassLoader(ClassLoader classLoader) {
        System.out.println(classLoader);
    }
}

任务调度

有时我们希望使用多线程来处理我们的结果或是执行一些定时任务,到达指定时间再去执行。这时我们首先想到的就是创建一个新的线程来处理,或是使用TimerTask来完成定时

异步任务

异步任务执行,需要使用Spring异步任务支持,在配置类上添加@EnableAsync注解:

@EnableAsync
@Configuration
public class MainConfig {
    ...

接着在需要异步执行的方法上添加@Async注解,即可将此方法标记为异步,当此方法被调用时,会异步执行,也就是新开一个线程执行,而不是在当前线程执行:

@Component
public class Student{
    public void syncTest() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"我是同步执行的方法,开始...");
        Thread.sleep(5000);
        System.out.println("我是同步执行的方法,结束!");
    }

    @Async
    public void asyncTest() throws InterruptedException {
        System.out.println(Thread.currentThread().getName()+"我是异步执行的方法,开始...");
        Thread.sleep(5000);
        System.out.println("我是异步执行的方法,结束!");
    }
}

测试:

public static void main(String[] args) throws InterruptedException {
    ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
    Student stu = context.getBean(Student.class);
    stu.asyncTest();    // 异步执行
    stu.syncTest();     // 同步执行
}

执行结果显示:异步执行的任务是在其他线程启动的,所以说并不会在当前线程阻塞,可以看到马上就开始执行下一行代码,调用同步执行的任务了。

定时任务

定时任务即就是指定在哪个时候再去执行。Spring中的定时任务是全局性质的,当Spring程序启动后,定时任务也就跟着启动了,可以在配置类上添加@EnableScheduling注解:

@EnableScheduling
@Configuration
public class MainConfig {
	...

接着直接在配置类里面编写定时任务,把要做的任务写成方法,并添加@Scheduled注解:

@EnableScheduling
@Configuration
public class MainConfig {

    @Scheduled(fixedRate = 2000)   //单位是毫秒,这里是每两秒钟打印一次
    public void task(){
        System.out.println("我是定时任务!"+new Date());
    }
    
    ...

@Scheduled中有很多参数,这里需要指定’cron’, ‘fixedDelay(String)’, or 'fixedRate(String)'的其中一个,否则无法创建定时任务:

  • fixedDelay:在上一次定时任务执行完之后,间隔多久继续执行。
  • fixedRate:无论上一次定时任务有没有执行完成,两次任务之间的时间间隔。
  • cron:如果嫌上面两个不够灵活,你还可以使用cron表达式来指定任务计划。

监听器

监听实际上就是等待某个事件的触发,当事件触发时,对应事件的监听器就会被通知。

要编写监听器,只需要让Bean继承ApplicationListener就可以了,并且将类型指定为对应的Event事件,这样,当发生某个事件时就会通知我们:

@Component
public class TestListener implements ApplicationListener<ContextRefreshedEvent> {
	// ContextRefreshedEvent 事件会在Spring容器初始化完成会触发一次
    @Override
    public void onApplicationEvent(ContextRefreshedEvent event) {
        System.out.println(event.getApplicationContext());
    }
}

当然,还可以自定义事件:

// 自定义事件
public class TestEvent extends ApplicationEvent {   //自定义事件需要继承ApplicationEvent
    public TestEvent(Object source) {
        super(source);
    }
}
// 编写监听器
@Component
public class TestListener implements ApplicationListener<TestEvent> {
    @Override
    public void onApplicationEvent(TestEvent event) {
        System.out.println("发生了一次自定义事件,成功监听到!");
    }
}
// 设定在定时任务中每秒钟发生一次这个事件
@Component
public class TaskComponent  implements ApplicationEventPublisherAware {
    ApplicationEventPublisher publisher;

    @Scheduled(fixedRate = 1000)   //一秒一次
    public void task(){
        publisher.publishEvent(new TestEvent(this));
    }

    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }
    
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值