Spring注解驱动

SpringBoot注解驱动

SpringBoot的事件监听

事件监听三大步。首先创建一个事件,然后创建一个监听器,再创建一个事件发布类。
事件的监听是在bean创建完成之后执行的,refresh()的最后一步执行:
事件类:事件类要继承ApplicationEvent这个抽象类,抽象类可以通过匿名内部类实现(如果没有抽象方法则大括号可以为空)

package com.hxh.event;

import org.springframework.context.ApplicationEvent;

import javax.validation.constraints.NotNull;

/**
 * @author Hanxiaohan
 * @date 2021/03/19 15:32
 * @since 1.0
 * <p>Copyright: Copyright (c) 2021</p>
 */
public class SelfEvent extends ApplicationEvent {
    /**
     * Create a new {@code ApplicationEvent}.
     *
     * @param source the object on which the event initially occurred or with
     *               which the event is associated (never {@code null})
     */

    private static final long serialVersionUID = 1L;

    private String message;
    public SelfEvent(@NotNull Object source, String message) {
        super(source);
        this.message=message;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

创建监听类:监听类继承ApplicationListener,泛型指定固定类型。
默认的Object source只有getSource()方法。可以添加其他属性(比如message)。

/**
 * @author Hanxiaohan
 * @date 2021/03/19 15:46
 * @since 1.0
 * <p>Copyright: Copyright (c) 2021</p>
 */
@Component
public class SignalListener implements ApplicationListener<SelfEvent> {

    @Override
    public void onApplicationEvent(SelfEvent event) {
        System.out.println("test#####  " + event.getMessage());
    }
}

发布事件:事件的发布需要调用容器ApplicationContext,通过其publishEvent(),参数可以是ApplicationEvent或者自己设定的其他Event类。

/**
 * @author Hanxiaohan
 * @date 2021/03/19 15:50
 * @since 1.0
 * <p>Copyright: Copyright (c) 2021</p>
 */
@Component
public class EventPublisher {

    @Resource
    private Ginger ginger;

    @Autowired
    ApplicationContext applicationContext;
    public void publish(String message){
        applicationContext.publishEvent(new SelfEvent(ginger,ginger.toString()+ message));
    }

}

本示例使用了一个普通bean作为source

@Component
public class Ginger {
    @Value("China")
    private String local;

    @Value("3.14159")
    private Double price;

    @Override
    public String toString() {
        return "Ginger{" +
                "local='" + local + '\'' +
                ", price=" + price +
                '}';
    }

    public String getLocal() {
        return local;
    }

    public void setLocal(String local) {
        this.local = local;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

测试调用:

@SpringBootTest
class ExtendsApplicationTests03 {

   @Autowired
   private EventPublisher eventPublisher;

   @Test
   void contextLoads() {
      eventPublisher.publish("卖生姜啦,预防脱发很有效!");
   }

}

运行结果:

test#####  Ginger{local='China', price=3.14159}卖生姜啦,预防脱发很有效!

ps:上面的监听使用了自己创建的SelfEvent event类型,如果使用ApplicationEvent,会把系统的事件也监听出来。

使用注解监听事件:@EventListener,可以添加多个class
但是监听方法只能有一个参数。

@Component
public class WoFe {
    @EventListener({ApplicationEvent.class})
    public void listten(ApplicationEvent event){
            if(event.getSource().getClass() == Ginger.class){
                System.out.println("注解实现:::    " + ((SelfEvent)event).getMessage());
            }
            else{
                System.out.println("注解实现:::   而我在等你"+event.getSource());
            }
    }
 。。。
注解实现:::   而我在等你[DefaultTestContext@2e3967ea testClass = ExtendsApplicationTests03, 
注解实现:::    Ginger{local='China', price=3.14159}卖生姜啦,预防脱发很有效!
注解实现:::   而我在等你[DefaultTestContext@2e3967ea testClass = ExtendsApplicationTests03, 
。。。
关于Spring *PostProcessor的总结
/**
* bean的生命周期:
* bean存在注册信息(ImportBeanDefinitionRegistrar)-->被加载到beanfactory-->被创建实例
* -->属性赋值(populate)-(BeanPostProcessor,*Aware)->初始化-->销毁
* 
* beanfactory历程:
* spring首先创建beanfactory,然后标准初始化beanfactory。。
* 然后执行BeanFactoryPostProcessor(包含两个接口)
* 
* BeanFactoryPostProcessor及其子接口
* BeanDefinitionRegistryPostProcessor
* 根据实现PriorityOrder接口执行子接口先。
* 再然后执行“注册BeanPostProcessor”。
* 
* ApplicationContextAware:属性赋值之后,初始化之前
* BeanPostProcessor:在属性赋值之后,初始化之前
* BeanNameAware:同上,可修改beanname;
* BeanFactoryAware:在属性赋值之后,初始化之前
 *
 * BeanPostProcessor:Bean后置处理器,在bean对象初始化前后进行拦截工作。
 * 1,BeanFactoryPostProcessor
 *   在beanfactory标准初始化之后调用:所有的bean的定义已经加载到beanFactory但是还没有被
 *   创建实例。可覆盖属性赋值。
 *
 * 2,BeanDefinitionRegistryPostProcessor继承了BeanFactoryPostProcessor
 * postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
 * 在所以bean定义信息将要被加载,bean实例还未被创建的时候执行。
 */

测试BeanDefinitionRegistryPostProcessor:

/**
 * registries that hold bean definitions
 *
 * BeanDefinitionRegistry 为bean定义的存储中心;以后BeanFactory就是
 * 按照BeanDefinitionRegistry里面保存的每一个bean定义信息创建bean实例。
 *
 */
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {

        System.out.println("postProcessBeanDefinitionRegistry...bean的数量:"+registry.getBeanDefinitionCount()+"!");
        RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Student.class);
        registry.registerBeanDefinition("mmp",rootBeanDefinition);


        AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(Student.class).getBeanDefinition();
        registry.registerBeanDefinition("mmlgb",beanDefinition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        System.out.println("MyBeanDefinitionRegistryPostProcessor...bean的数量:"+beanFactory.getBeanDefinitionCount()+"!");

    }
}

测试BeanFactoryPostProcessor
一个函数式接口,使用lambda表达式。

@Configuration
@Import({MyImportBeanDefinitionRegistrar.class})
public class MainConfig {

    @Bean
    public BeanFactoryPostProcessor beanFactoryPostProcessor1(){

        return ele -> {
        int beanDefinitionCount = ele.getBeanDefinitionCount();
        String[] beanDefinitionNames = ele.getBeanDefinitionNames();
        System.out.println("当前beanfactory中有"+beanDefinitionCount+"个bean!");
        System.out.println(Arrays.asList(beanDefinitionNames));
        };
    }
}

测试ImportBeanDefinitionRegistrar,使用注解导入bean:@Import({MyImportBeanDefinitionRegistrar.class})

/**
 * AnnotationMetadata: 当前类的注解信息
 * BeanDefinitionRegistry:
 * 注册类把所有需要添加到容器中的bean
 * 调用registerBeanDefinitions手工注册进来
 */
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry){
        boolean mmb1 = registry.containsBeanDefinition("mmp");
        boolean mmb2 = registry.containsBeanDefinition("mmlgb");
        if(!mmb1 && !mmb2){
            registry.registerBeanDefinition("goodbye", new RootBeanDefinition(Student.class));
            System.out.println("注册进去goodbye");
        }
    }
}

测试BeanPostProcessor

@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        if(o.getClass()==Lp.class){
            System.out.println("3+6= 9");
        }

        return o;
    }

    @Override
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
    
        if(s.equals("mmp")){
            System.out.println("-3-6= -9");

        }

        return o;
    }
}
几种*Aware反注入的实现

运行在bean实例化之后,初始化方法执行之前:

/**
 * @author Hanxiaohan
 * @date 2021/03/16 10:04
 * @since 1.0.1
 * <p>Copyright: Copyright (c) 2021</p>
 */
@Component
public class NiuPi implements ApplicationContextAware , BeanNameAware, EmbeddedValueResolverAware, EnvironmentAware {
    @Autowired
    private Lp lb;

    private StringValueResolver stringValueResolver;

    @Override
    public String toString() {
        return "NiuPi{" +
                "lb=" + lb +
                '}';
    }

    private ApplicationContext application;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.application=applicationContext;
        for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
            System.out.println(beanDefinitionName);
        }
    }

    @Override
    public void setBeanName(String name) {
        System.out.println(name);
    }

    @Override
    public void setEmbeddedValueResolver(StringValueResolver stringValueResolver) {
        this.stringValueResolver=stringValueResolver;
        System.out.println(stringValueResolver.resolveStringValue("#{7.8*75*0.35}"));
    }

    @Override
    public void setEnvironment(Environment environment) {
        System.out.println(environment.getProperty("os.name"));
    }
}

@Primary与@Scope 注解含义

@Configuration
public class Cai {

//    @Scope("prototype")
    @Primary
    @Bean("mmp")
    public Lv lv1(){
        Lv lv = new Lv();
        lv.setAge(100);
        return lv;
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值