springboot的Initializer的使用:
package com.hurricane.learn.springboot.standard.initializer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
/**
* 因为这个类的initialize方法调用是在spring容器中的bean还没有开始初始化的时刻,
* 因此,通过@Component注解是无法使其生效的。<br/>
* 使用方式有两种,分别为:<br/>
* 1.application.addInitializers(new MyApplicationContextInitializer());
* 2.将org.springframework.context.ApplicationContextInitializer=com.hurricane.learn.springboot.initializer.MyApplicationContextInitializer
* 放置到META-INF/spring.factories文件中
* @author Hurricane
* @date 2018年4月8日
* @version 1.0
*/
public class MyApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>{
private static final Logger logger = LoggerFactory.getLogger(MyApplicationContextInitializer.class);
@Override
public void initialize(ConfigurableApplicationContext context) {
logger.debug("========MyApplicationContextInitializer initialize=============");
}
}
第一种添加Initializer的方式为:
SpringApplication application = new SpringApplication(App.class);
application.addInitializers(new MyApplicationContextInitializer());
ConfigurableApplicationContext context = application.run(args);
springboot的Listener的使用:
event定义:
package com.hurricane.learn.springboot.standard.event;
import org.springframework.context.ApplicationEvent;
public class MyEvent extends ApplicationEvent{
private static final long serialVersionUID = 1L;
public MyEvent(Object source) {
super(source);
}
}
listener的定义:
package com.hurricane.learn.springboot.standard.listener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import com.hurricane.learn.springboot.standard.event.MyEvent;
/**
* 使用方式有两种,分别为:<br/>
* 1.application.addListeners(new MyApplicationListener());
* 2.org.springframework.context.ApplicationListener=com.hurricane.learn.springboot.listener.MyApplicationListener
* @author Hurricane
* @date 2018年4月8日
* @version 1.0
*/
public class MyApplicationListener implements ApplicationListener<MyEvent>{
private static final Logger logger = LoggerFactory.getLogger(MyApplicationListener.class);
@Override
public void onApplicationEvent(MyEvent event) {
logger.debug("=======event为:{}=========",event);
}
}
使用spring的上下文进行event的发布:
package com.hurricane.learn.springboot.standard;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.hurricane.learn.springboot.standard.event.MyEvent;
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
context.publishEvent(new MyEvent("myevent"));
context.close();
}
}
添加listener的方式与添加Initializer的方式类似。
springboot内置了一些事件(event)如ContextStoppedEvent,可以通过查看ApplicationEvent类的继承关系来选择使用。
springboot的ApplicationRunner与CommandLineRunner的使用:
ApplicationRunner的定义:
package com.hurricane.learn.springboot.standard.runner;
import java.util.Iterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
/**
* 可以识别的参数格式为:--abc=def
* @author Hurricane
* @date 2018年4月8日
* @version 1.0
*/
@Component
public class MyApplicationRunner implements ApplicationRunner{
private static final Logger logger = LoggerFactory.getLogger(MyApplicationRunner.class);
@Override
public void run(ApplicationArguments args) throws Exception {
logger.debug("=====MyApplicationRunner 传入参数有:{}=====",args.getOptionNames());
Iterator<String> iterator = args.getOptionNames().iterator();
while (iterator.hasNext()) {
String string = (String) iterator.next();
logger.debug("=====MyApplicationRunner 参数名{}:参数值:{}=====",string,args.getOptionValues(string));
}
}
}
CommandLineRunner的定义:
package com.hurricane.learn.springboot.standard.runner;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;
/**
* 可以识别的参数格式为:--abc=def
* @author Hurricane
* @date 2018年4月8日
* @version 1.0
*/
@Component
public class MyCommandLineRunner implements CommandLineRunner{
private static final Logger logger = LoggerFactory.getLogger(MyCommandLineRunner.class);
@Override
public void run(String... args) throws Exception {
for (String string : args) {
logger.debug("=====MyCommandLineRunner 传入参数有:{}=====",string);
}
}
}
ApplicationRunner与CommandLineRunner的功能(解析传入参数)类似,只是对于传入参数--abc=def aa --dd=ff bb,
ApplicationRunner会忽略掉aa、bb两个参数,只是用--abc=def --dd=ff,并解析为参数名与参数值。
而对于CommandLineRunner会简单地输出传入的参数,将空格作为参数的分隔符。
为了让ApplicationRunner与CommandLineRunner起作用,只需要将他们放置到spring的容器中即可。
springboot的@Import注解的使用:
1.定义一个注解:
package com.hurricane.learn.springboot.standard.config.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.Import;
import com.hurricane.learn.springboot.standard.config.selector.LogSelector;
/**
* 注入的spring容器中的bean若在指定包下,则进行日志输出
* @author Hurricane
* @date 2018年4月9日
* @version 1.0
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(LogSelector.class)
public @interface EnableLog {
String[] packages();
}
2.编写一个与该注解配合使用的Selector类:
package com.hurricane.learn.springboot.standard.config.selector;
import java.util.Arrays;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.stereotype.Component;
import org.springframework.util.MultiValueMap;
@Component
public class LogSelector implements ImportSelector,BeanPostProcessor{
private static final Logger logger = LoggerFactory.getLogger(LogSelector.class);
private static String[] packages;
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
MultiValueMap<String, Object> allAnnotationAttributes = importingClassMetadata.getAllAnnotationAttributes("com.hurricane.learn.springboot.standard.config.annotation.EnableLog");
List<Object> list = allAnnotationAttributes.get("packages");
String[] object = (String[]) list.get(0);
packages = object;
logger.info("LogSelector 将bean加入到spring容器中");
return new String[]{"com.hurricane.learn.springboot.standard.entity.Product","com.hurricane.learn.springboot.standard.entity.User"};
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName)
throws BeansException {
if (packages!=null)
for (int i = 0; i < packages.length; i++) {
if (bean.getClass().getName().startsWith(packages[i])) {
logger.debug("bean:{} 初始化开始.",beanName);
}
}
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName)
throws BeansException {
if (packages!=null)
for (int i = 0; i < packages.length; i++) {
if (bean.getClass().getName().startsWith(packages[i])) {
logger.debug("bean:{} 初始化结束.",beanName);
}
}
return bean;
}
}
LogSelector只需实现ImportSelector接口即可,但是为了实现指定的功能(输出指定包下注入到spring的bean),这里同时实现了BeanPostProcessor接口。
使用上面的@EnableLog注解:
package com.hurricane.learn.springboot.standard;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;
import com.hurricane.learn.springboot.standard.config.annotation.EnableLog;
import com.hurricane.learn.springboot.standard.config.selector.LogSelector;
@EnableLog(packages="com.hurricane")
@SpringBootApplication
public class App {
public static void main(String[] args) {
ConfigurableApplicationContext context = SpringApplication.run(App.class, args);
LogSelector bean = context.getBean(LogSelector.class);
System.out.println(bean);
context.close();
}
}
单独使用@Import注解时,注意:
* 注解@Import会把value指定的class导入到spring容器中,但是如果指定的class实现了ImportSelector接口,
* 则不会将自身导入到spring容器中,但是ImportSelector接口中selectImports方法返回的值(类的全路径)会导入到spring容器中