SpringCloud学习教程之DiscoveryClient的深⼊探究
前⾔
当我们使⽤@DiscoveryClient注解的时候,会不会有如下疑问:它为什么会进⾏注册服务的操作,它不是应该⽤作服务发现的吗?下⾯我们就来深⼊的探究⼀下其源码。
⼀、Springframework的LifeCycle接⼝
要搞明⽩这个问题我们需要了解⼀下这个重要的接⼝:
/*
* Copyright 2002-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* /licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package t;
/**
* A common interface defining methods for start/stop lifecycle control.
* The typical use case for this is to control asynchronous processing.
* <b>NOTE: This interface does not imply specific auto-startup semantics.
* Consider implementing {@link SmartLifecycle} for that purpose.</b>
*
* <p>Can be implemented by both components (typically a Spring bean defined in a
* Spring context) and containers (typically a Spring {@link ApplicationContext}
* itself). Containers will propagate start/stop signals to all components that
* apply within each container, e.g. for a stop/restart scenario at runtime.
*
* <p>Can be used for direct invocations or for management operations via JMX.
* In the latter case, the {@link org.port.MBeanExporter}
* will typically be defined with an
* {@link org.port.assembler.InterfaceBasedMBeanInfoAssembler},
* restricting the visibility of activity-controlled components to the Lifecycle
* interface.
*
* <p>Note that the Lifecycle interface is only supported on <b>top-level singleton
* beans</b>. On any other component, the Lifecycle interface will remain undetected
* and hence ignored. Also, note that the extended {@link SmartLifecycle} interface
* provides integration with the application context's startup and shutdown phases.
*
* @author Juergen Hoeller
* @since 2.0
* @see SmartLifecycle
* @see ConfigurableApplicationContext
* @see org.springframework.jms.listener.AbstractMessageListenerContainer
* @see org.springframework.scheduling.quartz.SchedulerFactoryBean
*/
public interface Lifecycle {
/**
* Start this component.
* <p>Should not throw an exception if the component is already running.
* <p>In the case of a container, this will propagate the start signal to all
* components that apply.
* @see SmartLifecycle#isAutoStartup()
*/
void start();
/**
* Stop this component, typically in a synchronous fashion, such that the component is
* fully stopped upon return of this method. Consider implementing {@link SmartLifecycle}
* and its {@code stop(Runnable)} variant when asynchronous stop behavior is necessary.
* <p>Note that this stop notification is not guaranteed to come before destruction: On
* regular shutdown, {@code Lifecycle} beans will first receive a stop notification before
* the general destruction callbacks are being propagated; however, on hot refresh during a
* context's lifetime or on aborted refresh attempts, only destroy methods will be called.
* <p>Should not throw an exception if the component isn't started yet.
* <p>In the case of a container, this will propagate the stop signal to all components
* that apply.
* @see SmartLifecycle#stop(Runnable)
* @see org.springframework.beans.factory.DisposableBean#destroy()
*/
void stop();
/**
* Check whether this component is currently running.
* <p>In the case of a container, this will return {@code true} only if <i>all</i>
* components that apply are currently running.
* @return whether the component is currently running
*/
boolean isRunning();
}
该接⼝定义启动/停⽌⽣命周期控制⽅法,当spring ioc容器启动或停⽌时将发送⼀个启动或者停⽌的信号通知到各个组件,因此我们可以在对应的⽅法⾥做我们想要的事情。我们可以通过类图发现我们常⽤的ClasspathXmlApplicationContext类就实现了该接⼝
下⾯我们来简单演⽰⼀下案例,创建类MyLifeCycle:
package org.hzgj.t;
import t.SmartLifecycle;
public class MyLifeCycle implements SmartLifecycle {
@Override
public void start() {
System.out.println("MyLifeCycle start ....");
}
@Override
public void stop() {
System.out.println("MyLifeCycle stop .....");
}
@Override
public boolean isRunning() {
return false;
}
@Override
public boolean isAutoStartup() {
return true;
}
@Override
public void stop(Runnable callback) {
}
@Override
public int getPhase() {
System.out.println("phase");
return 10;
}
}
在这⾥我们继承SmartLifeCycle该接⼝继承了LifeCycle, isRunning⽅法⽤于检测当前的组件是否处在运⾏状态,注意只有当isRunning返回值为false才可以运⾏
我们把MyLifeCycle配置到spring配置⽂件⾥,通过ClassPathXmlApplicationContext运⾏会得到如下结果:
另外在这⾥的getPhase⽅法,这个是定义阶段值(可以理解为优先级,值越⼩对应的LifeCycle越先执⾏)
⼆、DiscoveryClient源码探究
@EnableDiscoveyClient
/
*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* /licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
springcloud难学吗
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.client.discovery;
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 t.annotation.Import;
/**
* Annotation to enable a DiscoveryClient implementation.
* @author Spencer Gibb
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(EnableDiscoveryClientImportSelector.class)
public @interface EnableDiscoveryClient {
/
**
* If true, the ServiceRegistry will automatically register the local server.
*/
boolean autoRegister() default true;
}
请注意 @Import(EnableDiscoveryClientImportSelector.class) 我们可以参考⼀下这个类:
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* /licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.client.discovery;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.cloudmons.util.SpringFactoryImportSelector;
import Ordered;
import annotation.AnnotationAttributes;
import annotation.Order;
import nv.ConfigurableEnvironment;
import nv.Environment;
import nv.MapPropertySource;
import ype.AnnotationMetadata;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
/**
* @author Spencer Gibb
*/
@Order(Ordered.LOWEST_PRECEDENCE - 100)
public class EnableDiscoveryClientImportSelector
extends SpringFactoryImportSelector<EnableDiscoveryClient> {
@Override
public String[] selectImports(AnnotationMetadata metadata) {
String[] imports = super.selectImports(metadata);
AnnotationAttributes attributes = AnnotationAttributes.fromMap(
boolean autoRegister = Boolean("autoRegister");
if (autoRegister) {
List<String> importsList = new ArrayList<>(Arrays.asList(imports));
importsList.add("org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationConfiguration"); imports = Array(new String[0]);
} else {
Environment env = getEnvironment();
if(ConfigurableEnvironment.class.isInstance(env)) {
ConfigurableEnvironment configEnv = (ConfigurableEnvironment)env;
LinkedHashMap<String, Object> map = new LinkedHashMap<>();
map.put("spring.cloud.abled", false);
MapPropertySource propertySource = new MapPropertySource(
"springCloudDiscoveryClient", map);
}
}
return imports;
}
@Override
protected boolean isEnabled() {
return new RelaxedPropertyResolver(getEnvironment()).getProperty(
"spring.abled", Boolean.class, Boolean.TRUE);
}
@Override
protected boolean hasDefaultFactory() {
return true;
}
}
这个类重写的⽅法来⾃于接⼝ ImportSelector,我们可以根据 if(autoRegister)下的代码追踪到
类:org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegistration,我们来看⼀下结构图:
我们可以得知这个类实现了Lifecycle接⼝,那么我们看⼀看start⽅法,此⽅法在它的⽗类AbstractDiscoveryLifecycle⾥:
/*
* Copyright 2013-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* /licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.client.discovery;
import urrent.atomic.AtomicBoolean;
import urrent.atomic.AtomicInteger;
import javax.annotation.PreDestroy;
import org.apachemons.logging.Log;
import org.apachemons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.t.embedded.EmbeddedServletContainerInitializedEvent;
import org.springframework.cloud.client.discovery.event.InstanceRegisteredEvent;
import org.springframework.cloud.client.serviceregistry.ServiceRegistry;
import t.ApplicationContext;
import t.ApplicationContextAware;
import t.ApplicationListener;
import nv.Environment;
/**
* Lifecycle methods that may be useful and common to various DiscoveryClient implementations.
*
* @deprecated use {@link org.springframework.cloud.client.serviceregistry.AbstractAutoServiceRegi
stration} instead. This class will be removed in the next release train. *
* @author Spencer Gibb
*/
@Deprecated
public abstract class AbstractDiscoveryLifecycle implements DiscoveryLifecycle,
ApplicationContextAware, ApplicationListener<EmbeddedServletContainerInitializedEvent> {
private static final Log logger = Log(AbstractDiscoveryLifecycle.class);
private boolean autoStartup = true;
private AtomicBoolean running = new AtomicBoolean(false);
private int order = 0;
private ApplicationContext context;
private Environment environment;
private AtomicInteger port = new AtomicInteger(0);
protected ApplicationContext getContext() {
return context;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
}
@Deprecated
protected Environment getEnvironment() {
return environment;
}
@Deprecated
protected AtomicInteger getPort() {
return port;
}
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
@Override
public void stop(Runnable callback) {
try {
stop();
} catch (Exception e) {
<("A problem occurred attempting to stop discovery lifecycle", e);
}
callback.run();
}
@Override
public void start() {
if (!isEnabled()) {
if (logger.isDebugEnabled()) {
logger.debug("Discovery Lifecycle disabled. Not starting");
}
return;
}
// only set the port if the nonSecurePort is 0 and this.port != 0
if (() != 0 && getConfiguredPort() == 0) {
setConfiguredPort(());
}
/
/ only initialize if nonSecurePort is greater than 0 and it isn't already running
// because of containerPortInitializer below
if (!() && getConfiguredPort() > 0) {
register();
if (shouldRegisterManagement()) {
registerManagement();
}
getConfiguration()));
this.runningpareAndSet(false, true);
}
}
@Deprecated
protected abstract int getConfiguredPort();
@Deprecated
protected abstract void setConfiguredPort(int port);
/**
* @return if the management service should be registered with the {@link ServiceRegistry} */
protected boolean shouldRegisterManagement() {
return getManagementPort() != null && ManagementServerPortUtils.t); }
/**
* @return the object used to configure the registration
*/
@Deprecated
protected abstract Object getConfiguration();
/**
* Register the local service with the DiscoveryClient
*/
protected abstract void register();
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论