加载顺序

问题起因:

      在spring-security配置类里面,配置了一个权限验证服务,此服务通过security内部某种机制注入spring,配置时,使用new对象的形式。

在类全局变量使用@value的形式希望加载配置项里面的配置,但是后台又希望放一些硬编码的默认配置,直接在构造方法里面追加配置,发现变量为null。此时类的相关配置还没装载完毕,在postcontract下,可以正常获取。

探究过程:

      借此机会,平时有项目启动时需要初始全局数据,或者启动时做数据处理数据的需求,稍微延伸一下,看下常用的一些监听,容器等的加载顺序,一次性弄清楚(欢迎大家补充)

本次考察范围包括:

1、 基于servilet的:监听器,过滤器,servlet,启动项目时加载顺序。这些类一般就提供了明确的初始方法,销毁方法,类内部的生命周期非常明确。

2、 spring中的:配置类,服务类,控制器类,启动时加载顺序。因为这些类没有明显的,类似servlet体系里面生命周期方法,需要添加一些方法或实现,来做具体监控,以便于以后在合适的时机做合适的事情。

3、 容器类的启用节点:

  • 构造方法
  • @PostConstruct标注方法,此方法会在类的依赖关系加载完毕后被执行;
  • 类继承InitializingBean接口,实现afterPropertiesSet方法,此方法在这个类所有配置,相关属性全部填装完毕后执行;
  • 类继承ApplicationListener<ContextRefreshedEvent>接口,实现onApplicationEvent方法,这是处理容器事件的一个回调方法,项目启动过程中,会有2次进入。

测试用例:

测试准备

1、正在开发spring-cloud项目,就用这个项目来测好了;

2、在spring-coud项目里面测试servlet的东西,要在启动类添加@ServletComponentScan注解;

@SpringBootApplication
@ServletComponentScan//启动扫描servlet相关
public class App 
{
    public static void main( String[] args )
    {
    	SpringApplication.run(App.class, args);
    }
}

3、开始在工程里面添加测试类,和输出信息,通过输出来观察顺序;

监听器

@WebListener
public class TestListener implements ServletContextListener{
    
    public TestListener() {
		System.out.println("TestListener=====================new");
	}

	@Override
	public void contextDestroyed(ServletContextEvent arg0) {
		System.out.println("Listener=========================contextDestroyed");
	}

	@Override
	public void contextInitialized(ServletContextEvent sce) {
		System.out.println("Listener=========================contextInitialized");
	}
}

过滤器

@WebFilter(filterName="TestFilter",value="/*")
public class TestFilter implements Filter{

    public TestFilter() {
		System.out.println("TestFilter======================new");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("TestFilter =========================init");
		Filter.super.init(filterConfig);
	}
	
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		System.out.println("TestFilter =========================do filter");
	}

}

Servlet类

@WebServlet(name = "firstServlet", urlPatterns = "/firstServlet") 
public class ServletTest extends HttpServlet{
    public ServletTest(){
		System.out.println("ServletTest=======================new");
		
	}

	@Override
	public void init(ServletConfig config) throws ServletException {
		// TODO Auto-generated method stub
		System.out.println("servletTest=====================  init");
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
		System.out.println("servletTest======================do get");
		super.doGet(req, resp);
	}
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		System.out.println("servletTest=====================destroy");
		
	}
}

 

spring配置类

package com.mbap.auth.config;

import javax.annotation.PostConstruct;

import org.springframework.context.annotation.Configuration;

@Configuration
public class TestConfig {
	private String id;
	
	public TestConfig() {
		super();
		System.out.println("myconfig========================new");
	}

	@PostConstruct
	public void myCoinfig() {
		System.out.println("myconfig========================postConstruct");
	}
}

spring 服务类

package com.mbap.auth.service;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Service;

@Service
public class TestService implements InitializingBean ,ApplicationListener<ContextRefreshedEvent>{

    public TestService() {
    	System.out.println("TestService================================构造方法new");
//    	permitAll.add("[GET]/mbap-pp/rest/system/menu/permission/permissionTree");
	}
    
    @PostConstruct
    public void init() {
    	System.out.println("TestService================================PostConstruct");
    }

    @Override
	public void onApplicationEvent(ContextRefreshedEvent event) {
    	System.out.println("TestService===================on event");
		if(event.getApplicationContext().getParent() == null){//root application context 没有parent
           System.out.println("TestService======projectName-servlet context");
        }
        
		if(event.getApplicationContext().getDisplayName().equals("Root WebApplicationContext")){
			System.out.println("TestService======root application context");
		
		}
	}


	@Override
	public void afterPropertiesSet() throws Exception {
		// TODO Auto-generated method stub
		System.out.println("TestService================================afterPropertiesSet");
		
	}
}

 

spring 控制器

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.mbap.auth.service.TestService;

@RestController
@RequestMapping("/test/")
public class TestController {
	
	@Autowired
	private TestService service;
	
	@PostConstruct
	private void init() {
		System.out.println("TestController==================postConstruct");
	}
}

 

控制台输出

ServletTest=======================new
TestFilter======================new
TestListener=====================new
//由此看出servlet类加载顺序servlet/Filter/Listener


Listener=========================contextInitialized
TestFilter =========================filter init
//这里输出结果看出:servlet类初始化Listener>Filter


//spring相关开始初始化启动
myconfig========================new
myconfig========================postConstruct
TestService================================构造方法new
TestService================================PostConstruct
TestService================================afterPropertiesSet
TestController==================postConstruct
TestService===================on event

//===>在浏览器访问servlet页面,查看控制台
servletTest ========================init
TestFilter =========================do filter
servletTest ========================do Get(预期输出,但是没有输出,还没弄清楚咋回事,有空再看)

 

结论

 

 

 

参考资料

https://segmentfault.com/a/1190000019093670

https://blog.csdn.net/xiaojin21cen/article/details/83418470?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-4&spm=1001.2101.3001.4242

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值