SpringBoot-自定义starter

一. 先完成自定义starter

(一)新建maven jar工程

工程名为zdy-spring-boot-starter,导入依赖:

<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-autoconfigure</artifactId>
			<version>2.2.9.RELEASE</version>
		</dependency>

(二)编写javaBean

package com.lagou.pojo;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;


@EnableConfigurationProperties
@ConfigurationProperties(prefix = "simplebean")
public class SimpleBean {

	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	@Override
	public String toString() {
		return "SimpleBean{" +
				"id=" + id +
				", name='" + name + '\'' +
				'}';
	}
}

(三)编写配置类MyAutoConfiguration

package com.lagou.config;

import com.lagou.pojo.SimpleBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@ConditionalOnBean(ConfigMarker.class)//该注解的意思是在上下文中必须存在ConfigMarker.class这个bean,才会让当前自动配置类生效
public class MyAutoConfiguration {

	static {

		System.out.println("MyAutoConfiguration init.... ");
	}

	@Bean
	public SimpleBean simpleBean(){
		return new SimpleBean();
	}



}

(四)resources下创建/META-INF/spring.factories

注意: META-INF 是自己手动创建的目录, spring.factories 也是手动创建的文件 , 在该文件中配置自
己的自动配置类

 

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.lagou.config.MyAutoConfiguration
上面这句话的意思就是 SpringBoot 启动的时候会去加载我们的 simpleBean IOC 容器中。这其实
是一种变形的 SPI 机制

二. 使用自定义starter

(一)创建工程spring-boot-mytest,导入依赖

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
		 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.2.9.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>

	<groupId>com.lagou</groupId>
	<artifactId>spring-boot-mytest</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring-boot-mytest</name>
	<description>Demo project for Spring Boot</description>

	<properties>
		<java.version>11</java.version>
	</properties>

	<packaging>jar</packaging>

	<dependencies>


		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
			<!--<exclusions>
				<exclusion>
					<groupId>org.springframework.boot</groupId>
					<artifactId>spring-boot-starter-tomcat</artifactId>
				</exclusion>
			</exclusions>-->
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<dependency>
			<groupId>com.lagou</groupId>
			<artifactId>zdy-spring-boot-starter</artifactId>
			<version>1.0-SNAPSHOT</version>
		</dependency>

	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>

</project>

(二)在全局配置文件中配置属性值

server.port=8080


simplebean.id=1
simplebean.name=子慕

(三)编写测试方法

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootMytestApplicationTests {

	@Autowired
	private SimpleBean simpleBean;

	@Test
	public void contextLoads() {
		System.out.println(simpleBean);
	}
}

三. 热插拔技术

还记得我们经常会在启动类 Application 上面加 @EnableXXX 注解吗?

 

其实这个 @Enablexxx 注解就是一种热拔插技术,加了这个注解就可以启动对应的 starter ,当不需
要对应的 starter 的时候只需要把这个注解注释掉就行,是不是很优雅呢?那么这是如何实现的
呢?

(一)改造zdy工程新增热插拔支持类

1. 新增标记类ConfigMarker

package com.lagou.config;

public class ConfigMarker {
}

2. 新增EnableRegisterServer注解

package com.lagou.config;


import org.springframework.context.annotation.Import;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Import(ConfigMarker.class)//该注解将某个组件类生成实例,添加到容器中
public @interface EnableRegisterServer {
}

3. 改造 MyAutoConfiguration

新增条件注解 @ConditionalOnBean(ConfigMarker.class)
@ConditionalOnBean 这个是条件注解,前面的意思代表只有当期上下文中含有 ConfigMarker
对象,被标注的类才会被实例化。
@ConditionalOnBean(ConfigMarker.class)//该注解的意思是在上下文中必须存在ConfigMarker.class这个bean,才会让当前自动配置类生效
public class MyAutoConfiguration {}

(二)改造service工程

在启动类上新增@EnableImRegisterServer注解

package com.lagou;

import com.lagou.config.EnableRegisterServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;


@SpringBootApplication//标注在类上说明这个类是`SpringBoot`的主配置类
@EnableRegisterServer
public class SpringBootMytestApplication{

	public static void main(String[] args) {
		SpringApplication.run(SpringBootMytestApplication.class, args);
	}

/*	@Override
	protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
		// 这里要指向核心启动类
		return builder.sources(SpringBootMytestApplication.class);
	}*/
}
到此热插拔就实现好了,当你加了 @EnableImRegisterServer 的时候启动 zdy 工程就会自动装配
SimpleBean ,反之则不装配。
让的原理也很简单,当加了 @EnableImRegisterServer 注解的时候,由于这个注解使用了
@Import({ConfigMarker.class}) ,所以会导致 Spring 去加载 ConfigMarker 到上下文中,而
又因为条件注解 @ConditionalOnBean(ConfigMarker.class) 的存在,所以
MyAutoConfiguration 类就会被实例化。

四. 关于条件注解

  • @ConditionalOnBean:仅仅在当前上下文中存在某个对象时,才会实例化一个Bean
  • @ConditionalOnClass:某个class位于类路径上,才会实例化一个Bean
  • @ConditionalOnExpression:当表达式为true的时候,才会实例化一个Bean。基于SpEL达式的条件判断。
  • @ConditionalOnMissingBean:仅仅在当前上下文中不存在某个对象时,才会实例化一个 Bean
  • @ConditionalOnMissingClass:某个class类路径上不存在的时候,才会实例化一个Bean
  • @ConditionalOnNotWebApplication:不是web应用,才会实例化一个Bean
  • @ConditionalOnWebApplication:当项目是一个Web项目时进行实例化。
  • @ConditionalOnNotWebApplication:当项目不是一个Web项目时进行实例化。
  • @ConditionalOnProperty:当指定的属性有指定的值时进行实例化。
  • @ConditionalOnJava:当JVM版本为指定的版本范围时触发实例化。
  • @ConditionalOnResource:当类路径下有指定的资源时触发实例化。
  • @ConditionalOnJndi:在JNDI存在的条件下触发实例化。
  • @ConditionalOnSingleCandidate:当指定的Bean在容器中只有一个,或者有多个但是指定了首选的Bean时触发实例化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值