天天看点

Spring中使用ApplicationEvent机制,实际项目开发使用

Spring中使用事件非常简单,只需要以下的几个步骤:

  • 1.定义事件,继承ApplicationEvent
  • 2.定义监听,要么实现ApplicationListener接口,要么在方法上添加@EventListener注解
  • 3.定义发布事件借口,调用ApplicationContext.publishEvent()或者ApplicationEventPublisher.publishEvent();
  • 4.业务调用发布事件

业务场景: 注册账号完成之后,需要将账号信息同步到权限平台。

————————————————————————————————————————————————————————————

1.首先定义一个事件(Event)

1.1实际项目:

@Data
public class BaseAsgardEvent<T> extends ApplicationEvent {
    private T data;

    public BaseAsgardEvent(Object source) {
        super(source);
    }

    public BaseAsgardEvent(Object source,T data){
        super(source);
        this.data = data;
    }
}
           

1.2参考别人文档:

//自定义事件需要继承ApplicationEvent
public class UserRegisterEvent extends ApplicationEvent {
    private String username;
    public UserRegisterEvent(Object source, String username) {
        super(source);
        this.username = username;
    }
    public String getUsername() {
        return username;
    }
}
           

2.定义一个事件监听器(Listener)

2.1 定义事件监听器两种方式

//可以实现ApplicationListener接口监听事件
@Component
@Order(2)//可以使用order指定顺序,越小优先级越高
public class MailUserRegisterListener implements ApplicationListener<UserRegisterEvent> {
    @Override
    public void onApplicationEvent(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName()+"-给用户"+event.getUsername()+"发送邮件!");
    }
}
//也可以使用@EventListener监听事件
@Component
@Order(1)
public class CouponUserRegisterListener {
    @EventListener
    public void sendCoupon(UserRegisterEvent event) {
        System.out.println(Thread.currentThread().getName()+"-给用户"+event.getUsername()+"发送优惠券!");
    }
}
           

2.2 实际项目:

@Component
@Slf4j
public class AccountEventListener {

    @Autowired
    UniformAccessClient uniformAccessClient;
    @Autowired
    AccountMapper accountMapper;


    @EventListener
    public void merchantBusinessRecordEventListener(BaseAsgardEvent<Account> event) {

        Account account = event.getData();
        try {
            if (account == null) {
                return;
            }
            AccountPO accountPO = accountMapper.selectByPrimaryKey(account.getId());
            //调用权限平台服务,同步信息
            uniformAccessClient.syncAccountToUniformAccessClient(accountPO);
        } catch (Exception e) {
            log.error("商户档案变更,同步发送消息失败", e);
        }
    }


}
           

3.发布事件方法,这里包装ApplicationContext方法使用

@Component
public class SpringContextHolder implements ApplicationContextAware {

    private static ApplicationContext applicationContext = null;

    /**
     * 获取静态变量中的ApplicationContext.
     */
    public static ApplicationContext getApplicationContext() {
        assertContextInjected();
        return applicationContext;
    }

    /**
     * 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
     */
    @SuppressWarnings("unchecked")
    public static <T> T getBean(String name) {
        assertContextInjected();
        return (T) applicationContext.getBean(name);
    }

    /**
     * 从静态变量applicationContext中得到Bean, 自动转型为所赋值对象的类型.
     */
    public static <T> T getBean(Class<T> requiredType) {
        assertContextInjected();
        return applicationContext.getBean(requiredType);
    }

    /**
     * 清除SpringContextHolder中的ApplicationContext为Null.
     */
    public static void clearHolder() {
        applicationContext = null;
    }

    /**
     * 实现ApplicationContextAware接口, 注入Context到静态变量中.
     */
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        SpringContextHolder.applicationContext = applicationContext;
    }

    /**
     * 检查ApplicationContext不为空.
     */
    private static void assertContextInjected() {
        Validate.validState(applicationContext != null,
                "applicaitonContext属性未注入, 请在applicationContext.xml中定义SpringContextHolder.");
    }


    //包装方法
    public static void publish(Object event) {
        applicationContext.publishEvent(event);
    }



}
           

4.实际使用:

@Service
public class TestMethod {


    
    public void store(Account account) {
    //处理账号业务。。。。。。。。。。。
    //处理其他业务完成。。。。。。。。。。。

        //商户账号 同步
        BaseAsgardEvent<Account> event = new BaseAsgardEvent<Account>("ACCOUNT", account);
        SpringContextHolder.publish(event);

    }
    }