SpringBoot应用(二)---扩展使用

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,并解析为参数名与参数值。

扫描二维码关注公众号,回复: 1584201 查看本文章

而对于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容器中









猜你喜欢

转载自blog.csdn.net/hurricane_li/article/details/80666232