基础知识

spring事务

spring关于事务提供了两种编程模型,注解和接口编程。

基于注解:① xml文件开启注解驱动,相关类和方法上通过@Transactional注解标识。② spring在启动是会为这些class生成spring内部管理的bean,若是发现带有@Transactional注解的类和方法,会为其生成代理类,代理类中会做相关的事物处理(正常提交,异常回滚)。



基于接口:需要实现TransactionCallback接口。



spring事务传播属性
常量名称 常量解释
PROPAGATION_REQUIRED(propagation_required) 支持当前事物,如果当前没有事物,就新建一个事物。这是最常见的选择,也是spring默认的事物传播。
PROPAGATION_REQUIRES_NEW(propagation_requires_new) 新建事物,如果当前存在事物,就把当前事物挂起。新建的事物和挂起的事物没有任何的关系,是两个独立的事物。外层事物失败回滚之后,不能回滚内层事物执行的结果。内层事物失败抛出异常,外层事物捕获,也可以不处理回滚操作。
PROPAGATION_SUPPORTS(propagation_supports) 支持当前事物,如果当前没有事物,就以非事物的方式执行。
PROPAGATION_MANDATORY(propagation_mandatory) 支持当前事物,如果当前没有事物,就抛出异常。
PROPAGATION_NOT_SUPPORTED(propagation_not_supported) 以非事物方式执行操作,如果当前存在事物,就把当前事物挂起。
PROPAGATION_NEVER(propagation_never) 以非事物方式执行操作,如果当前存在事物,就抛出异常。
PROPAGATION_NESTED(propagation_nested) 如果一个活动的事务存在,则运行在一个嵌套的事务中。如果没有活动事务,则按REQUIRED属性执行。它使用了一个单独的事务,这个事务拥有多个可以回滚的保存点。内部事务的回滚不会对外部事务造成影响。它只对DataSourceTransactionManager事务管理器起效。
数据库事务隔离级别
隔离级别 隔离级别的值 导致的问题
Read Uncommited 0 允许脏读,不可重复读,幻读
Read Commited 1 避免脏读,允许不可重复读和幻读
RepeatableRead 2 避免脏读和不可重复读,允许幻读
Serializable 3 避免脏读 ,不可重复读,幻读,事物一个一个执行,执行效率低
spring事务隔离级别
常量名称 常量解释
ISOLATION_DEFAULT(isolation_default) PlatfromTransactionManager默认的事物隔离级别,使用数据库默认的事物隔离级别。
ISOLATION_READ_UNCOMMITTED(isolation_read_uncommitted) 读未提交
ISOLATION_READ_COMMITTED(isolation_read_committed) 读已提交
ISOLATION_REPEATABLE_READ(isolation_repeatable) 可重复读
ISOLATION_SERIALIZABLE(isolation_serializable) 串行化
参考

深入了解spring事务原理

Restful风格

一致性hash

注解驱动

元注解(Meta-Annotations)

所谓元注解,是指能够声明在其他注解上的注解,若是一个注解标注在其他注解上,那么他就是元注解。如java@Documented @Repeatable @Inherited等注解,spring@Component等注解。


spring内建模式注解

spring中提供了诸如@Repository @Service @Controller @Configuration等的注解,用以标记某一领域内的对象,故称这类注解为模式注解。这些注解均派生自@Component,spring可以通过这些注解的元标注@Component来扫描并注册这些组件。

// @Controller注解定义
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Controller {
String value() default "";
}

自定义模式注解
// 自定义派生注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface StringRepository {
/**
* 属性方法名称必须与@Component#value()一致
* @return
*/
String value() default "";
}

// 被自定义注解修饰的bean
@StringRepository(value = "stringService")
public class StringService {
public List<String> findAll(){
return Arrays.asList("jack", "tom", "seven");
}
}

// 启动类
public class App {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
context.setConfigLocation("classpath:beans1.xml");
context.refresh();
StringService stringService = (StringService)context.getBean("stringService");
System.out.printf("stringService.findAll() = %s \n", stringService.findAll());
}
// 输出结果
// stringService.findAll() = [jack, tom, seven]
}
<!-- beans1.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config/>

<context:component-scan base-package="com.study.annotation.component"/>
</beans>

原理分析

spring 会在初始化解析xml 文件时读取 /META-INF/spring.handlers 文件中的配置,该配置文件中定义了一些命名空间的处理类。比如 context 命名空间的处理类为 ContextNamespaceHandleraop命名空间的处理类为AopNamespaceHandler。这些命名空间处理类在spring应用上下文启动时,调用其init方法。该方法会去注册该命名空间下所有local元素的Bean定义解析器。如context命名空间处理类会去注册annotation-configcomponent-scanBean定义解析器。

// spring.handlers文件
http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler
http\://www.springframework.org/schema/aop=org.springframework.aop.config.AopNamespaceHandler
public class ContextNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
...
// 注册annotation-config解析器
registerJava5DependentParser("annotation-config", "org.springframework.context.annotation.AnnotationConfigBeanDefinitionParser");
// 注册component-scan解析器
registerJava5DependentParser("component-scan", "org.springframework.context.annotation.ComponentScanBeanDefinitionParser");
...
}
}

关于<context:component-scan>元素的Bean定义解析器ComponentScanBeanDefinitionParser。该类实现了BeanDefinitionParser接口,解析至该元素时,会去调用parse方法。

// ComponentScanBeanDefinitionParser处理
public class ComponentScanBeanDefinitionParser implements BeanDefinitionParser {
...
// 包扫描路径
private static final String BASE_PACKAGE_ATTRIBUTE = "base-package";
// 使用默认过滤器属性
private static final String USE_DEFAULT_FILTERS_ATTRIBUTE = "use-default-filters";

private static final String RESOURCE_PATTERN_ATTRIBUTE = "resource-pattern";

@Override
public BeanDefinition parse(Element element, ParserContext parserContext) {
// 1. 解析 base-package 属性,获取到一个扫包路径数组
String basePackage = element.getAttribute(BASE_PACKAGE_ATTRIBUTE);
basePackage = parserContext.getReaderContext().getEnvironment().resolvePlaceholders(basePackage);
String[] basePackages = StringUtils.tokenizeToStringArray(basePackage,
ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
// 2. 配置 ClassPathBeanDefinitionScanner 对象
ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element);
// 3. ClassPathBeanDefinitionScanner执行 doScan 方法,获取 BeanDefinitionHolder集合
Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);
// 4. 注册集合中的这些 BeanDefinitionHolder
registerComponents(parserContext.getReaderContext(), beanDefinitions, element);
return null;
}

/**************配置ClassPathBeanDefinitionScanner**************/
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) {
// 1. 关于 use-default-filters 属性,若是用户配置了,取用户配置的值,否则默认为 true
boolean useDefaultFilters = true;
if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) {
useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));
}
// 2. 调用 createScanner 方法创建一个 ClassPathBeanDefinitionScanner 对象,并设置相关属性
ClassPathBeanDefinitionScanner scanner = createScanner(parserContext.getReaderContext(), useDefaultFilters); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns());
// 3. 若是元素中包含 resource-pattern 属性
if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) {
scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE));
}
try {
parseBeanNameGenerator(element, scanner);
}
catch (Exception ex) {
...
}
try {
parseScope(element, scanner);
}
catch (Exception ex) {
...
}
parseTypeFilters(element, scanner, parserContext);
return scanner;
}

// 创建一个 ClassPathBeanDefinitionScanner对象
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) {
return new ClassPathBeanDefinitionScanner(
readerContext.getRegistry(), useDefaultFilters,
readerContext.getEnvironment(), readerContext.getResourceLoader());
}
...
}

ClassPathBeanDefinitionScanner执行doScan方法

// ClassPathBeanDefinitionScanner处理
public class ClassPathBeanDefinitionScanner extends ClassPathScanningCandidateComponentProvider {
// BeanDefinition注册器
private final BeanDefinitionRegistry registry;
// Environment环境
private Environment environment;

private BeanDefinitionDefaults beanDefinitionDefaults = new BeanDefinitionDefaults();


public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) {
this(registry, true);
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters) {
this(registry, useDefaultFilters, getOrCreateEnvironment(registry));
}

public ClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment) {

this(registry, useDefaultFilters, environment,
(registry instanceof ResourceLoader ? (ResourceLoader) registry : null));
}

// 构造函数 BeanDefinitionRegistry useDefaultFilters Environment ResourceLoader
public ClassPathBeanDefinitionScanner(
BeanDefinitionRegistry registry, boolean useDefaultFilters,
Environment environment, ResourceLoader resourceLoader) {
// 1. 设置 BeanDefinitionRegistry
this.registry = registry;
// 2. 若是使用默认过滤器,执行父类 ClassPathScanningCandidateComponentProvider方法
if (useDefaultFilters) {
registerDefaultFilters();
}
// 3. 父类 ClassPathScanningCandidateComponentProvider 方法
setEnvironment(environment);
// 4. 父类 ClassPathScanningCandidateComponentProvider 方法
setResourceLoader(resourceLoader);
}


/************************doScan方法****************/
protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
// 1. 创建一个存储 BeanDefinitinHolder的集合
Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>();
// 2. 循环遍历给定的包路径数组
for (String basePackage : basePackages) {
// 3. 调用 findCandidateComponents 方法找到给定包下的 BeanDefinition
Set<BeanDefinition> candidates = findCandidateComponents(basePackage);
// 4. 遍历这些 BeanDefinition
for (BeanDefinition candidate : candidates) {
// 5.获取scope元信息ScopeMetadata并设置到candidate的scope属性中,如:single
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate);
candidate.setScope(scopeMetadata.getScopeName());
// 6. 为这个 candidate 生成一个 beanName
String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry);
// 7. 若是 candidate 是 AbstractBeanDefinition 的子类,调用 postProcessBeanDefinition方法
if (candidate instanceof AbstractBeanDefinition) {
postProcessBeanDefinition((AbstractBeanDefinition) candidate, beanName);
}
// 8. 若是 candidiate 是 AnnotatedBeanDefinition 的子类
if (candidate instanceof AnnotatedBeanDefinition) { AnnotationConfigUtils.processCommonDefinitionAnnotations((AnnotatedBeanDefinition) candidate);}
// 9. 调用 checkCandidate 方法检验
if (checkCandidate(beanName, candidate)) {
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName);
definitionHolder =
AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
beanDefinitions.add(definitionHolder);
registerBeanDefinition(definitionHolder, this.registry);
}
}
}
// 返回BeanDefinitionHolder集合,在类 ComponentScanBeanDefinitionParser 中注册
return beanDefinitions;
}
...
}

ClassPathScanningCandidateComponentProvider

public class ClassPathScanningCandidateComponentProvider implements EnvironmentCapable, ResourceLoaderAware {
// 组件包含项过滤器列表
private final List<TypeFilter> includeFilters = new LinkedList<TypeFilter>();
// 组件排除项过滤器列表
private final List<TypeFilter> excludeFilters = new LinkedList<TypeFilter>();
// MetadataReaderFactory->CachingMetadataReaderFactory
private MetadataReaderFactory metadataReaderFactory;

private ResourcePatternResolver resourcePatternResolver;

// 通过给定的包路径寻找候选组件
public Set<BeanDefinition> findCandidateComponents(String basePackage) {
// 1. 创建一个集合,用以存储 BeanDefinition
Set<BeanDefinition> candidates = new LinkedHashSet<BeanDefinition>();
try {
// 2. 将包路径(com.study.annotation.component)转化为class文件路径
// (classpath*:com/study/annotation/component/**/*.class)
String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX +
resolveBasePackage(basePackage) + '/' + this.resourcePattern;
// 3. 将class文件路径转化packageSearchPath转化为Resource数组
Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath);
// 4. 循环遍历Resource数组
for (Resource resource : resources) {
// 5.若是这个资源Resource可读
if (resource.isReadable()) {
try {
// 6.获取这个资源Resource的MetadataReader对象
MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource);
// 7. 判断metadataReader是否是候选组件
//org.springframework.core.type.classreading.SimpleMetadataReader
if (isCandidateComponent(metadataReader)) {
// 8. 生成一个 ScannedGenericBeanDefinition对象
ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader);
sbd.setResource(resource);
sbd.setSource(resource);
// 9.若ScannedGenericBeanDefinition是候选组件,加入到candidates中
if (isCandidateComponent(sbd)) {
...
candidates.add(sbd);
} else {
...
}
} else {
...
}
} catch (Throwable ex) {
throw new BeanDefinitionStoreException();
}
} else {
...
}
}
} catch (IOException ex) {
throw new BeanDefinitionStoreException();
}
return candidates;
}


// 判断给定的 MetadataReader 是否是候选组件(SimpleMetadataReader)
protected boolean isCandidateComponent(MetadataReader metadataReader) throws IOException {
// 循环排除项过滤器
for (TypeFilter tf : this.excludeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return false;
}
}
// 循环包含项过滤器
for (TypeFilter tf : this.includeFilters) {
if (tf.match(metadataReader, this.metadataReaderFactory)) {
return isConditionMatch(metadataReader);
}
}
return false;
}

private boolean isConditionMatch(MetadataReader metadataReader) {
if (this.conditionEvaluator == null) {
this.conditionEvaluator = new ConditionEvaluator(getRegistry(), getEnvironment(), getResourceLoader());
}
return !this.conditionEvaluator.shouldSkip(metadataReader.getAnnotationMetadata());
}


// 判断给定的 AnnotatedBeanDefinition 是否是候选组件
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
// 1. 获取AnnotatedBeanDefinition的AnnotationMetadata注解元信息,实现类为
// org.springframework.core.type.classreading.AnnotationMetadataReadingVisitor
AnnotationMetadata metadata = beanDefinition.getMetadata();
return (metadata.isIndependent() && (metadata.isConcrete() ||
(metadata.isAbstract() && metadata.hasAnnotatedMethods(Lookup.class.getName()))));
}

// 注册默认的过滤器->@Component @ManagedBean @Named
protected void registerDefaultFilters() {
this.includeFilters.add(new AnnotationTypeFilter(Component.class));
ClassLoader cl = ClassPathScanningCandidateComponentProvider.class.getClassLoader();
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.annotation.ManagedBean", cl)), false));
} catch (ClassNotFoundException ex) {
...
}
try {
this.includeFilters.add(new AnnotationTypeFilter(
((Class<? extends Annotation>) ClassUtils.forName("javax.inject.Named", cl)), false));

} catch (ClassNotFoundException ex) {
...
}
}

// 设置环境Environment
public void setEnvironment(Environment environment) {
this.environment = environment;
this.conditionEvaluator = null;
}

@Override
public void setResourceLoader(@Nullable ResourceLoader resourceLoader) {
// 设置resourcePatternResolver
this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader);
// 设置metadataReaderFactory
this.metadataReaderFactory = new CachingMetadataReaderFactory(resourceLoader);
this.componentsIndex = CandidateComponentsIndexLoader.loadIndex(this.resourcePatternResolver.getClassLoader());
}
}

关于MetadataReaderFactory

// 顶层接口,提供两种方式获取MetadataReader->className和Resource
public interface MetadataReaderFactory {
MetadataReader getMetadataReader(String className) throws IOException;
MetadataReader getMetadataReader(Resource resource) throws IOException;
}

public class SimpleMetadataReaderFactory implements MetadataReaderFactory {

private final ResourceLoader resourceLoader;

// 根据给定的Resource返回一个MetadataReader对象
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
return new SimpleMetadataReader(resource, this.resourceLoader.getClassLoader());
}
}


public class CachingMetadataReaderFactory extends SimpleMetadataReaderFactory {
public static final int DEFAULT_CACHE_LIMIT = 256;
private volatile int cacheLimit = DEFAULT_CACHE_LIMIT;
// Resource->MetadataReader映射
private final Map<Resource, MetadataReader> metadataReaderCache =
new LinkedHashMap<Resource, MetadataReader>(DEFAULT_CACHE_LIMIT, 0.75f, true){
@Override
protected boolean removeEldestEntry(Map.Entry<Resource, MetadataReader> eldest) {
return size() > getCacheLimit();
}
};

// 基于Resource方式获取MetadataReader
@Override
public MetadataReader getMetadataReader(Resource resource) throws IOException {
// 缓存限制小于等于0,直接调用父类SimpleMetadataReaderFactory方法获取
if (getCacheLimit() <= 0) {
return super.getMetadataReader(resource);
}
// 缓存限制大于0,锁定缓存
synchronized (this.metadataReaderCache) {
// 从缓存加载,若是加载不到,调用父类方法加载,存入缓存并返回
MetadataReader metadataReader = this.metadataReaderCache.get(resource);
if (metadataReader == null) {
metadataReader = super.getMetadataReader(resource);
this.metadataReaderCache.put(resource, metadataReader);
}
return metadataReader;
}
}

public int getCacheLimit() {
return this.cacheLimit;
}
}

关于MetadataReader

// 元信息读取接口
public interface MetadataReader {
// 获取资源信息Resource
Resource getResource();

// 获取Class的元信息ClassMetadata
ClassMetadata getClassMetadata();

// 获取注解Annotation的元信息AnnotationMetadata
AnnotationMetadata getAnnotationMetadata();
}

// 元信息读取接口的简单实现
class SimpleMetadataReader implements MetadataReader {

private final Resource resource;

private final ClassMetadata classMetadata;

private final AnnotationMetadata annotationMetadata;

// 构造方法,通过给定的Resource和ClassLoader创建一个SimpleMetadataReader对象
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
InputStream is = new BufferedInputStream(resource.getInputStream());
ClassReader classReader;
try {
classReader = new ClassReader(is);
} catch (IllegalArgumentException ex) {
throw new NestedIOException();
} finally {
is.close();
}
// 创建AnnotationMetadataReadingVisitor对象
AnnotationMetadataReadingVisitor visitor = new AnnotationMetadataReadingVisitor(classLoader);
classReader.accept(visitor, ClassReader.SKIP_DEBUG);
// 将SimpleMetadataReader的annotationMetadata和classMetadata属性均设置为visitor
this.annotationMetadata = visitor;
this.classMetadata = visitor;
// 将SimpleMetadataReader的resource设置为resource
this.resource = resource;
}

@Override
public Resource getResource() {
return this.resource;
}

@Override
public ClassMetadata getClassMetadata() {
return this.classMetadata;
}

@Override
public AnnotationMetadata getAnnotationMetadata() {
return this.annotationMetadata;
}
}

关于加载BeanDefinition时的过滤器 TypeFilter

// 上层接口
public interface TypeFilter {
boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException;
}
// 抽象类
public abstract class AbstractTypeHierarchyTraversingFilter implements TypeFilter {
// 是否考虑继承
private final boolean considerInherited;
// 是否考虑接口
private final boolean considerInterfaces;

// 实现上层接口 TypeFilter 的 match 方法
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
throws IOException {
// 1. 调用 matchSelf方法,若是返回 true,直接返回
if (matchSelf(metadataReader)) {
return true;
}
// 2. 获取 metadatdaReader的 ClassMetadata
ClassMetadata metadata = metadataReader.getClassMetadata();
if (matchClassName(metadata.getClassName())) {
return true;
}
// 3. 若时考虑继承,则匹配父类
if (this.considerInherited) {
// 从Class元信息ClassMetadata中判断该类是否有父类
if (metadata.hasSuperClass()) {
// 若是该类有父类,调用matchSuperClass方法
Boolean superClassMatch = matchSuperClass(metadata.getSuperClassName());
if (superClassMatch != null) {
if (superClassMatch.booleanValue()) {
return true;
}
} else {
try {
if (match(metadata.getSuperClassName(), metadataReaderFactory)) {
return true;
}
} catch (IOException ex) {
...
}
}
}
}
if (this.considerInterfaces) {
for (String ifc : metadata.getInterfaceNames()) {
Boolean interfaceMatch = matchInterface(ifc);
if (interfaceMatch != null) {
if (interfaceMatch.booleanValue()) {
return true;
}
} else {
try {
if (match(ifc, metadataReaderFactory)) {
return true;
}
} catch (IOException ex) {
...
}
}
}
}
return false;
}

protected boolean matchSelf(MetadataReader metadataReader) {
return false;
}

protected boolean matchClassName(String className) {
return false;
}

protected Boolean matchSuperClass(String superClassName) {
return null;
}

}
// 实现类
public class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter {

private final Class<? extends Annotation> annotationType;

private final boolean considerMetaAnnotations;


// MetadataReader时SimpleMetadataReader
@Override
protected boolean matchSelf(MetadataReader metadataReader) {
//获取到 MetadataReader 的注解元信息 AnnotationMetadata
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
//该MetadataReader直接被annotationType注解修饰返回true
//修饰该MetadataReader注解的元注解中有annotationType返回true
return metadata.hasAnnotation(this.annotationType.getName()) ||
(this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}

@Override
protected Boolean matchSuperClass(String superClassName) {
return hasAnnotation(superClassName);
}

protected Boolean hasAnnotation(String typeName) {
if (Object.class.getName().equals(typeName)) {
return false;
} else if (typeName.startsWith("java")) {
if (!this.annotationType.getName().startsWith("java")) {
return false;
}
try {
Class<?> clazz = ClassUtils.forName(typeName, getClass().getClassLoader());
return ((this.considerMetaAnnotations ? AnnotationUtils.getAnnotation(clazz, this.annotationType) :
clazz.getAnnotation(this.annotationType)) != null);
} catch (Throwable ex) {

}
}
return null;
}
}

关于ClassReader

// Class信息读取类ClassReader
public class ClassReader {

public ClassReader(final InputStream is) throws IOException {
this(readClass(is, false));
}


public void accept(final ClassVisitor classVisitor, final int flags) {
accept(classVisitor, new Attribute[0], flags);
}

public void accept(final ClassVisitor classVisitor,
final Attribute[] attrs, final int flags) {
...
}
}

关于AnnotationMetadata

/*************************** AnnotatioMetadata接口 **************/
public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {
Set<String> getAnnotationTypes();

Set<String> getMetaAnnotationTypes(String annotationName);

boolean hasAnnotation(String annotationName);

boolean hasMetaAnnotation(String metaAnnotationName);

boolean hasAnnotatedMethods(String annotationName);

Set<MethodMetadata> getAnnotatedMethods(String annotationName);
}

public interface ClassMetadata {
String getClassName();

boolean isInterface();

boolean isAnnotation();

boolean isAbstract();

boolean isConcrete();

boolean isFinal();

boolean isIndependent();

boolean hasEnclosingClass();

String getEnclosingClassName();

boolean hasSuperClass();

String getSuperClassName();

String[] getInterfaceNames();

String[] getMemberClassNames();
}


public interface AnnotatedTypeMetadata {

boolean isAnnotated(String annotationName);

Map<String, Object> getAnnotationAttributes(String annotationName);

Map<String, Object> getAnnotationAttributes(String annotationName, boolean classValuesAsString);

MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName);

MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValuesAsString);
}

关于ClassMetadataReadingVisitor

class ClassMetadataReadingVisitor extends ClassVisitor implements ClassMetadata {

private String enclosingClassName;

private boolean independentInnerClass;

private boolean isInterface;

private boolean isAbstract;


@Override
public boolean isIndependent() {
return (this.enclosingClassName == null || this.independentInnerClass);
}

@Override
public boolean isConcrete() {
return !(this.isInterface || this.isAbstract);
}

@Override
public boolean isAbstract() {
return this.isAbstract;
}
}

public abstract class ClassVisitor {

}

public interface ClassMetadata {

}

关于 AnnotationMetadataReadingVisitor

public class AnnotationMetadataReadingVisitor extends ClassMetadataReadingVisitor implements AnnotationMetadata {
@Override
public boolean hasAnnotatedMethods(String annotationName) {
for (MethodMetadata methodMetadata : this.methodMetadataSet) {
if (methodMetadata.isAnnotated(annotationName)) {
return true;
}
}
return false;
}

}

public interface AnnotationMetadata extends ClassMetadata, AnnotatedTypeMetadata {

}

public interface AnnotatedTypeMetadata {

}
// AnnotatedBeanDefinition基于注解的BeanDefinition
public interface AnnotatedBeanDefinition extends BeanDefinition {
AnnotationMetadata getMetadata();
MethodMetadata getFactoryMethodMetadata();
}

// GenericBeanDefinition层次性的BeanDefinition定义
public class GenericBeanDefinition extends AbstractBeanDefinition {
private String parentName;

public GenericBeanDefinition() {
super();
}

public GenericBeanDefinition(BeanDefinition original) {
super(original);
}

@Override
public void setParentName(String parentName) {
this.parentName = parentName;
}

@Override
public String getParentName() {
return this.parentName;
}

@Override
public AbstractBeanDefinition cloneBeanDefinition() {
return new GenericBeanDefinition(this);
}

@Override
public boolean equals(Object other) {
return (this == other || (other instanceof GenericBeanDefinition && super.equals(other)));
}

@Override
public String toString() {
StringBuilder sb = new StringBuilder("Generic bean");
if (this.parentName != null) {
sb.append(" with parent '").append(this.parentName).append("'");
}
sb.append(": ").append(super.toString());
return sb.toString();
}
}


// ScannedGenericBeanDefinition 基于扫描获取到的 BeanDefinition
public class ScannedGenericBeanDefinition extends GenericBeanDefinition implements AnnotatedBeanDefinition {
private final AnnotationMetadata metadata;

public ScannedGenericBeanDefinition(MetadataReader metadataReader) {
...
this.metadata = metadataReader.getAnnotationMetadata();
setBeanClassName(this.metadata.getClassName());
}


@Override
public final AnnotationMetadata getMetadata() {
return this.metadata;
}

@Override
public MethodMetadata getFactoryMethodMetadata() {
return null;
}

}
spring组合注解
spring注解属性别名和覆盖
Enable
条件装配

Unsafe

Unsafe类
// jdk核心类库可操作的api
public final class Unsafe {
// 对外暴露的实例属性,类加载阶段加载
private static final Unsafe theUnsafe;
static {
...
theUnsafe = new Unsafe();
...
}
private Unsafe() {}

// 该类中的 theUnsafe 属性为该类的一个实例,对外只提供给jdk核心类库使用。我们在平常的开发中无法通过该方法来获取 theUnsafe 对象。(可以通过万能的反射方式获取)
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}

// native方法,阻塞当前线程
public native void park(boolean var1, long var2);

// native方法,唤醒指定的线程
public native void unpark(Object var1);
}

Unsafe操作

获取Unsafe实例

由于Unsafe实例获取方法添加了类加载器验证,所以我们代码中编写的类是无法直接使用Unsafe类的。一般我们可以有两种方式获取Unsafe实例。① 从限制条件入手,修改引导类加载路径,将我们编写的路径添加到引导类路径中。② 通过反射的方式获取。

public static void main(String[] args) throws InterruptedException {
// 获取到Unsafe实例
Unsafe unsafe = getUnsafe();
System.out.println(unsafe);
}

// 1.通过反射获取 Unsafe 实例
private static Unsafe getUnsafe() {
Unsafe unsafe = null;
try {
Field field = Unsafe.class.getDeclaredField("theUnsafe");
field.setAccessible(true);
unsafe = (Unsafe)field.get(null);
} catch (Exception e) {
e.printStackTrace();
}
return unsafe;
}

非常规对象实例化

public static void main(String[] args) throws InterruptedException {
// 非常规对象实例化
People p1 = (People)getInstance(People.class);
People p2 = (People)getInstance(People.class);
System.out.println(p1);
System.out.println(p2);
// 输出结果
// null:0
// null:0
}
// 获取指定类的实例,该方式不会调用指定类的构造方法
public static Object getInstance (Class clazz) {
Unsafe unsafe = getUnsafe();
Object p = null;
try {
p = unsafe.allocateInstance(clazz);
} catch (InstantiationException e) {
e.printStackTrace();
}
return p;
}
// 可操作类
class People {
String name;
int age;

public People(){
this.name = "default";
this.age = 18;
}
public People(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return this.name + ":" + this.age;
}
}

多线程同步(CAS操作)

juc提供了一些原子操作类,这些类中使用了 Unsafe 类中提供的一些方法。

public class AtomicInteger extends Number implements java.io.Serializable {
// 获取到 Unsafe 类对象
private static final Unsafe unsafe = Unsafe.getUnsafe();
// value属性在内存地址中的偏移量
private static final long valueOffset;
// 静态代码块,初始化 valueOffset 属性
static {
try {
valueOffset = unsafe.objectFieldOffset
(AtomicInteger.class.getDeclaredField("value"));
} catch (Exception ex) { throw new Error(ex); }
}
// 该类所持有的值
private volatile int value;

// 获取当前值,并将其加1
// 调用 UnSafe 类的 getAndAddInt 方法,返回 this 对象上地址偏移量为 valueOffset 处的值,并将其加1
public final int getAndIncrement() {
return unsafe.getAndAddInt(this, valueOffset, 1);
}
}

public final class Unsafe {
...
// 某个对象的某个地址偏移处的值加上某个值,并将原始值返回
public final int getAndAddInt(Object var1, long var2, int var4) {
int var5;
do {
// 获取到原始值
var5 = this.getIntVolatile(var1, var2);
} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
return var5;
}
// 获取
public native int getIntVolatile(Object var1, long var2);
// CAS更新
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
...
}

挂起与恢复

LockSupport中提供了两个方法,parkunpark方法,而这两个方法实际上又是调用的Unsafe类中的native方法。park是将当前调用线程阻塞,而unpark方法则是唤醒指定的线程。

public class LockSupport {
// 加载 Unsafe 类型的 UNSAFE 实例
private static final sun.misc.Unsafe UNSAFE;
static {
try {
...
UNSAFE = sun.misc.Unsafe.getUnsafe();
...
} catch (Exception ex) { throw new Error(ex); }
}

// LockSupport提供了挂起当前线程的多个方法
public static void park() {
UNSAFE.park(false, 0L);
}

public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}

// 调用 Unsafe 类的unpark方法唤醒指定的线程
public static void unpark(Thread thread) {
if (thread != null) {
UNSAFE.unpark(thread);
}
}
}


public final class Unsafe {
...
// 操作系统底层提供的挂起线程的方法(阻塞线程)
public native void park(boolean var1, long var2);
// 操作系统底层提供的唤醒线程的方法(取消阻塞线程)
public native void unpark(Object var1);
// 几个过期的方法
// 获得对象锁(可重入锁)
@Deprecated
public native void monitorEnter(Object var1);
// 释放对象锁
@Deprecated
public native void monitorExit(Object var1);
// 尝试获取对象锁
@Deprecated
public native boolean tryMonitorEnter(Object var1);
...
}

内存管理

// 内存分配
public native long allocateMemory(long var1);
// 扩充内存
public native long reallocateMemory(long var1, long var3);
// 释放内存
public native void freeMemory(long var1);
// 在给定的内存块中设置值
public native void setMemory(Object var1, long var2, long var4, byte var6);
// 内存拷贝
public native void copyMemory(Object var1, long var2, Object var4, long var5, long var7);

// 关于堆外内存的使用
// 使用原因: 垃圾回收停顿的改善 提升程序IO操作的性能
// java实现堆外内存操作的类 DirectByteBuffer
class DirectByteBuffer extends MappedByteBuffer implements DirectBuffer {

}

数组操作


内存屏障

AQS


AQS类内部结构
public abstract class AbstractQueuedSynchronizer {

private transient volatile Node head; // 同步队列头节点
private transient volatile Node tail; // 同步队列尾节点
private volatile int state; // 锁状态值

static final class Node {
/*nextWaiter 属性的几个状态值*/
static final Node SHARED = new Node(); // 标记节点在共享模式下等待
static final Node EXCLUSIVE = null; // 标记节点在排他模式下等待
/*waitStatus 属性的几个状态值*/
static final int CANCELLED = 1; // 表示节点已经被取消
static final int SIGNAL = -1; // 表示后面节点的线程需要被唤醒。
static final int CONDITION = -2; // 表示节点在条件队列上
static final int PROPAGATE = -3; // 关于共享锁的状态

volatile int waitStatus;
volatile Node prev; // 前驱
volatile Node next; // 后继
volatile Thread thread; // 节点封装的线程
Node nextWaiter; // 下一个等待的节点
// addWaiter方法调用时,会构造一个Node节点
Node(Thread thread, Node mode) {
this.nextWaiter = mode;
this.thread = thread;
}
}
}

acquire方法

该方法定义为获取,ReentrantLock内部获取锁的操作会调用该方法。该方法的执行流程为:

① 执行tryAcquire,若是该方法返回为true,直接结束。否则执行下一步操作。(tryAcquire是一个空方法,具体逻辑由子类来实现)。

② 执行addWaiter方法,参数值为Node.EXCLUSIVE。① 该操作首先会将当前线程封装成为一个Node节点,该Node节点的thread值为当前线程,nextWaiter值为null。② 将创建好的该节点添加到同步队列的尾部。③ 将该节点返回。

③ 执行 acquireQueued(Node node, int arg)方法。该方法以自旋开始。① 获取到给定节点node的前驱节点p。若是p为头节点并且尝试获取锁成功,则将node节点设置为头节点(threadprev属性设置为null),将p节点清除,返回线程中断表标识。② 若上面条件不满足或执行失败,执行shouldParkAfterFailedAcquire方法和parkAndCheckInterrupt方法。③ 首先是会执行shouldParkAfterFailedAcquire(p, node)方法的,该方法是判断当前线程获取锁失败后,是否需要挂起。执行逻辑是:判断前一个节点pwaitStatus状态值,若是该值为Node.SIGNAL,返回true。其它情况返回false。④ 若是shouldParkAfterFailedAcquire(p, node)方法返回值为true,执行parkAndCheckInterrupt方法,否则执行 ①。⑤ parkAndCheckInterrupt方法首先将当前线程挂起,然后返回线程的中断标识,若是为true,会将interrupted属性设置为true

④ 由于acquireQueued(Node node, int agr)方法返回的是当前线程的中断标识,若是返回为true,立马中断当前线程。

public final void acquire(int arg) {
if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) {
selfInterrupt();
}
}
// 一个空方法,具体逻辑由子类来实现
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
// addWaiter方法,添加一个节点到同步队列
private Node addWaiter(Node mode) {
Node node = new Node(Thread.currentThread(), mode);
Node pred = tail;
if (pred != null) {
node.prev = pred;
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
// 添加一个节点到同步队列,直到成功为止
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
if (compareAndSetHead(new Node()))
tail = head;
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}

// 一段自旋操作中,成功获取到锁,该方法才会结束。
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}

// 将给定的节点设置为头节点,① head指向node ② node的thread属性指向null ③ node的prev属性指向null
private void setHead(Node node) {
head = node;
node.thread = null;
node.prev = null;
}

// 当尝试获取锁失败后,判断是否应该将当前的线程挂起
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
int ws = pred.waitStatus;
// 前一个节点waitStatus状态值为SIGNAL(-1),线程可以被安全的挂起
if (ws == Node.SIGNAL) {
return true;
}
// 若是前一个节点被取消了(1),跳过该节点
if (ws > 0) {
do {
// pred和node.prev重新赋值
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
// 将pred的next指向node节点
pred.next = node;
} else {
// 其它情况,CAS操作将 pred的状态值修改为 SIGNAL
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
// 挂起当前线程并且返回当前线程的中断状态
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}

release方法

ReentrantLockunlock方法中,会直接调用此方法。该方法也是一个模板方法,① 首先会去调用tryRelease(arg)方法,此方法在AQS中是一个空方法,具体逻辑由子类来实现。 ② 若是 ① 调用后返回值为true,执行unparkSuccessor(Node node)方法。unparkSuccessor(Node node)方法会去唤醒node节点的下一个节点。③ 若是 ① 调用后返回值为false,直接返回false

// 首先执行子类的tryRelease方法,根据其返回值执行具体的操作
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
return false;
}
// 抽象方法,由具体的子类来实现
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}
// 若是node节点存在后继节点,则将其唤醒
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0) {
compareAndSetWaitStatus(node, ws, 0);
}
Node s = node.next;
// 当node节点的next节点为null或者其已经被取消时,从尾节点向前遍历,找到一个节点
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev) {
if (t.waitStatus <= 0) {
s = t;
}
}
}
// 找到了一个不为null的节点,将其唤醒
if (s != null) {
LockSupport.unpark(s.thread);
}
}
Condition与ConditionObject

在AQS内部定义了一个类ConditionObject,该类实现了Condition接口。类直接的定义关系如下:

public abstract class AbstractQueuedSynchronizer{
...
public class ConditionObject implements Condition {
// 条件队列头节点
private transient Node firstWaiter;
// 条件队列尾节点
private transient Node lastWaiter;
}
...
}

await方法

该方法是将当前线程添加到条件队列上。执行逻辑:① 若是当前线程已经被打断,直接抛出异常。 ② 调用addConditionWaiter方法,将当前的线程封装成为一个 Node 节点,添加到等待队列的尾部,并返回该节点。③ 调用fullyRelease方法释放当前线程获取到的锁。④ while循环,调用 isOnSyncQueue 方法判断节点是否在同步队列,没在同步队列执行 while 循环体,挂起当前线程。

public final void await() throws InterruptedException {
// 判断中断,抛出异常
if (Thread.interrupted()) {
throw new InterruptedException();
}
// 添加到等待队列
Node node = addConditionWaiter();
// 释放该线程获取的锁
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
// 添加一个新的节点到等待队列。
// 1. 清除被取消的节点
// 2. 将当前线程封装成Node节点,添加到等待队列
private Node addConditionWaiter() {
Node t = lastWaiter;
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
lastWaiter = node;
return node;
}
// 释放当前线程获取到的锁
// 1. 获取到锁状态 state 的值
// 2. 调用 release 方法释放锁
// 3. 释放成功,返回state 之前的值。
// 4. 释放失败,抛出异常。
// 5. 若是释放失败,将当前线程节点的 waitStatus 状态值设置为 Node.CANCELLED(取消)
final int fullyRelease(Node node) {
boolean failed = true;
try {
int savedState = getState();
if (release(savedState)) {
failed = false;
return savedState;
} else {
throw new IllegalMonitorStateException();
}
} finally {
if (failed) {
node.waitStatus = Node.CANCELLED;
}
}
}
// 判定给定的节点是否在同步队列上
final boolean isOnSyncQueue(Node node) {
if (node.waitStatus == Node.CONDITION || node.prev == null) {
return false;
}
if (node.next != null) {
return true;
}
return findNodeFromTail(node);
}

signal方法

① 调用isHeldExclusively方法,返回false,直接抛出异常,否则执行下一步。② 获取到等待队列的第一个节点,将其做为参数,调用doSignal方法。③ doSignal方法会将给定的节点从等待队列放到同步队列的尾部。

public final void signal() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null) {
doSignal(first);
}
}
// 判断获取到锁的线程是否为当前线程
protected boolean isHeldExclusively() {
throw new UnsupportedOperationException();
}
// ReentrantLock的Sync的内部实现
protected final boolean isHeldExclusively() {
return getExclusiveOwnerThread() == Thread.currentThread();
}
// 将 first 节点从等待队列移动到同步队列
// 1. 将first节点从等待队列中去除
// 2. 调用 transferForSignal 方法将 first节点放到同步队列
// 3. 若是上一步失败,尝试下一个节点
private void doSignal(Node first) {
do {
if ( (firstWaiter = first.nextWaiter) == null) {
lastWaiter = null;
}
first.nextWaiter = null;
} while (!transferForSignal(first) && (first = firstWaiter) != null);
}
// 将 node 节点添加到同步队列的尾部
// 1. cas操作将 node 节点的 waitStatus 状态值由 Node.CONDITION修改为0,修改失败返回false。
// 2. 将node节点添加到同步队列的尾部
// 3. 若是node节点的waitStatus状态值大于0,或者将node节点的状态值设置为SIGNAL失败,唤醒该节点线程。
// 4. 返回 true。
final boolean transferForSignal(Node node) {
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
return false;
}
Node p = enq(node);
int ws = p.waitStatus;
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL))
LockSupport.unpark(node.thread);
return true;
}

signalAll方法

具体逻辑:大体和signal方法相同,但其会执行doSignalAll(first)方法而不是doSignal(first)方法。

public final void signalAll() {
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
Node first = firstWaiter;
if (first != null)
doSignalAll(first);
}
// 1. 清除等待队列 lastWaiter = firstWaiter = null;
// 2. 从 first节点开始,依次调用 transferForSignal方法,直到节点为null。
private void doSignalAll(Node first) {
lastWaiter = firstWaiter = null;
do {
Node next = first.nextWaiter;
first.nextWaiter = null;
transferForSignal(first);
first = next;
} while (first != null);
}

lambda和stream

参考文章1

参考文章2

功能性接口的简化

  1. lambda表达式可以简化RunnableComparator这种接口的写法。
/*****lambda表达式简化线程的创建*****/
// 普通写法
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// do something
}
});
// lambda写法
Thread t2 = new Thread(()->{
// do something
});

/*****lambda表达式简化 Collections.sort 排序*****/
// 普通写法
Collections.sort(list, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1 - o2;
}
});
// lambda写法
Collections.sort(list, (x, y) -> x - y);

/*****自定义功能接口*****/
List<String> params = Arrays.asList(new String[]{"app", "red", "blue"});
// 映射List中元素的length集合
List<Integer> res1 = new CollectionUtils<String, Integer>().map(params, (String param) -> param.length());
// 映射list中以元素的大写集合
List<String> res2 = new CollectionUtils<String, String>().map(params, (String param) -> param.toUpperCase());


// 定义函数式接口
@FunctionalInterface
interface MyOP<P, R> {
R apply(P obj);
}
// 集合操作类
class CollectionUtils<P, R> {
// 对集合中的元素进行操作,操作完成之后返回一个新的集合
public List<R> map(List<P> input, MyOP<P, R> myOp) {
List<R> result = new ArrayList();
for (P obj : input) {
result.add(myOp.apply(obj));
}
return result;
}
}
方法和构造方法的引用

// lambda表达式的一般写法
params.forEach((v) -> System.out.print(v + "\t"));
// lambda的简化写法
params.forEach(System.out::print);

// lambda构造方法的简写 Date::new
List<Long> dateValues = Arrays.asList(new Long[] {0L, 1000L});
List<Date> map = new CollectionUtils<Long, Date>().map(dateValues, Date::new);
接口的默认方法

1. 解决了接口的演化问题(接口中新增默认实现方法,不影响原先的实现类)
2. 实现了行为的多继承 (一个类可以实现多个接口的默认方法)
stream

Stream原理:流式操作,由 jdk 内部分配多个线程来执行 stream 内部的操作。并发流使用的默认线程数等于你机器的处理器核心数。

Stream场景:由于 Stream 是由 jdk 内部来为任务分配线程,所以在 一些耗时操作慎用 Stream。

Stream应用:Stream.of()方法,可以接收单个参数,也可以接收一个数组参数,将其转换为一个Stream对象。下面是几个Stream的简单应用demo。


(1)实例代码(forEach方法遍历)->接收一个参数, 通过forEach方法接收一个功能接口。

List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
Stream.of(list).forEach(System.out::println);
// 输出结果
// [1, 2, 3]

(2)实例代码(forEach方法遍历)->接收一个数组,通过forEach方法接收一个功能接口。

Stream.of(list.toArray()).forEach(System.out::println);
// 输出结果
// 1
// 2
// 3

(3)实例代码(filter方法过滤)-> 找处以小写字母’a’开头的字符串

Stream.of("Abc", "abc", "ccc", "asD")
.filter((str) -> {return str.startsWith("a");})
.forEach(System.out::println);
// 输出结果
// abc
// asD

(4)实例方法->(map方法建立映射)-> 统计给出数组中每个字符串的长度

Stream.of("A", "abc", "cc", "a")
.map((str) -> str.length())
.forEach(System.out::println);
// 输出结果
// 1
// 3
// 2
// 1

(5)实例方法->(reduce方法的使用) -> 初始值为 100,计算初始值加1到5的值

List<Integer> integerList = Arrays.asList(1, 2, 3, 4, 5);
int init = 100;
Integer result = integerList.stream()
.reduce(init, (a, b) -> a + b);
System.out.println("result->" + result);
// 输出结果
// 115

负载均衡

完善中。。。。

负载均衡算法基础(理论)

参考资料


负载均衡分类:客户端负载均衡 服务端负载均衡


负载均衡算法

​ 随机 轮询

​ 权重


Ribbon的实现(设计)

设计分析

// 核心接口
com.netflix.loadbalancer.IRule
com.netflix.loadbalancer.ILoadBalancer

// 服务实例定义实体
Netflix Eureka
com.netflix.appinfo.InstanceInfo

Spring Cloud Commons
org.springframework.cloud.client.ServiceInstance

Netflix Ribbon
com.netflix.loadbalancer.Server

ReentrantLock


类关系与锁初始化

ReentrantLock类内部有一个属性,Sync:sync,该属性对应的类是定义在ReentrantLock内部的一个静态类(抽象类)。ReentrantLock内部又为Sync定义了两个子类NonfairSyncFairSync。根据类名便可看到非公平与公平之分。我们通过api使用ReentrantLock类时,会调用其构造函数创建一个该类型的对象,构造函数可传参数true|false,确定创建公平或非公平锁。若没传递参数,会默认创建非公平锁。

// 几个类定义关系图
public class ReentrantLock{
...
private final Sync sync;

abstract static class Sync extends AbstractQueuedSynchronizer {

}
static final class NonfairSync extends Sync {
...
}
static final class FairSync extends Sync {
...
}
}

public abstract class AbstractQueuedSynchronizer{
...
}

// 默认创建非公平锁
public ReentrantLock() {
sync = new NonfairSync();
}
// 参数为 true 创建公平锁,false 创建非公平锁
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}

方法调用关系

调用ReentrantLock:lock方法或是ReentrantLock:unlock方法时,ReentrantLock会委托Sync来执行具体的上锁或者是释放锁的逻辑。① 关于lock,在Sync内部定义了一个抽象方法Sync:lock,在其子类FairSyncNonfairSync均实现了这个方法。这两个实现类的lock方法最终又会调用Sync的父类AQSacquire方法。② 关于unlock,实际上调用的是Sync的父类AQSrelease方法。

/*****ReentrantLock*****/
// 上锁,调用sync的lock方法
public void lock() {
sync.lock();
}
// 解锁,调用sync的父类aqs的release方法
public void unlock() {
sync.release(1);
}
/*****Sync*****/
// 上锁-> 抽象方法,具体逻辑由子类FairSync或NonfairSync来实现
abstract void lock();
// 解锁-> Sync的父类AbstractQueuedSynchronizer定义的方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}

// FairSync类实现的lock方法
final void lock() {
acquire(1);
}
// NonfairSync类实现的lock方法
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}

lock之公平与非公平

NonfairSync:lock方法在执行时,首先会通过CAS操作直接修改锁状态state的值,若是执行成功,则成功获取到锁,若是执行失败,调用AbstractQueuedSynchronizer:acquire(1)方法来执行普通的上锁逻辑。FairSync:lock方法在执行时,直接调用 AbstractQueuedSynchronizer:acquire(1)方法来执行普通的上锁逻辑。(非公平锁直接忽略了排队等待获取锁的线程)

/*****NonfairSync*****/
final void lock() {
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
acquire(1);
}
/*****FairSync*****/
final void lock() {
acquire(1);
}

② 在上面的分析中,非公平锁的实现类在尝试设置锁失败时,直接调用AQSacquire方法,而公平锁的实现类直接调用AQSacquire方法。AQS:acquire方法属于一个模板方法,内部定义了获取锁的操作步骤。其中tryAcquire方法是其第一个调用的方法,也是一个没有实现的空方法,具体的实现逻辑由其子类来实现。

NonfairSync:tryAcquire方法内部会调用其父类的Sync:nonfairTryAcquire方法,该方法语义为非公平尝试获取。具体逻辑:首先判断锁的状态,若是没有线程获取到锁,执行通过CAS操作修改锁状态,若是成功返回true。若是未成功,继续判断获取锁的线程是否为当前线程,若是当前线程,将锁状态值加上方法传入的值,并将锁状态值更新(可重入),返回true,否则返回false

FairSync:tryAcquire方法的执行逻辑:判断是 否有线程获取到锁,若是没有线程获取到锁,继续判断是否有线程等待获取锁,若是无线程等待获取锁,CAS操作获取锁,成功返回true。操作获取锁失败,或者有线程等待获取锁,或者已有线程获取到锁,继续判断当前获取到锁的线程是否为当前线程,是则执行可重入锁操作并返回true,否则返回false

/*****AbstractQueuedSynchronizer *****/
// AQS中定义的获取锁的模板方法
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
// 一个未实现的方法,具体逻辑由子类来实现
protected boolean tryAcquire(int arg) {
throw new UnsupportedOperationException();
}
/*****NonfairSync*****/
protected final boolean tryAcquire(int acquires) {
return nonfairTryAcquire(acquires);
}
/*****Sync*****/
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

/*****FairSync*****/
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (!hasQueuedPredecessors() &&
compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0)
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}

unlock执行逻辑

调用ReentrantLock:unlock方法时,Sync会调用父类的AbstractQueuedSynchronizer:release方法。

具体逻辑是:① 首先tryRelease方法会被调用,而这个方法在AQS中是一个没有具体实现的空方法,具体逻辑由子类Sync来实现。② 子类中首先会去判断当前线程是否就是获取到锁的线程,若不是直接抛出异常,否则执行下一步的逻辑。③ 获取到锁状态state的值,并用state值减去方法传的参数值(释放多少次),计算出一个结果。④ 若是计算出来的这个结果为0,将state的值设置为0,并将获取锁的线程设置为null,并返回true。⑤ 若是计算出来的这个结果不为0,将state的值设置为计算得到的值,返回false

子类执行完tryRelease方法后,会返回一个值。① 若是该值为trueAQS:release方法会执行其它逻辑,执行完返回true。② 若是该值为falseAQS:release方法直接返回false

/*****ReentrantLock *****/
public void unlock() {
sync.release(1);
}

/*****AbstractQueuedSynchronizer *****/
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
protected boolean tryRelease(int arg) {
throw new UnsupportedOperationException();
}

/*****Sync*****/
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}

LockSupport与Unsafe

LockSupport中提供了两个方法,parkunpark方法,而这两个方法实际上又是调用的Unsafe类中的native方法。park是将当前调用线程阻塞,而unpark方法则是唤醒指定的线程。

public class LockSupport {
// jdk内部用于操作内存地址的类
private static final sun.misc.Unsafe UNSAFE;

static {
try {
...
UNSAFE = sun.misc.Unsafe.getUnsafe();
...
} catch (Exception ex) { throw new Error(ex); }
}

// 调用 Unsafe 类的park方法将当前线程阻塞
public static void park(Object blocker) {
Thread t = Thread.currentThread();
setBlocker(t, blocker);
UNSAFE.park(false, 0L);
setBlocker(t, null);
}
// 调用 Unsafe 类的unpark方法唤醒指定的线程
public static void unpark(Thread thread) {
if (thread != null) {
UNSAFE.unpark(thread);
}
}
}

// jdk核心类库可操作的api
public final class Unsafe {

private static final Unsafe theUnsafe;
static {
...
theUnsafe = new Unsafe();
...
}
private Unsafe() {}

// 该类中的 theUnsafe 属性为该类的一个实例,对外只提供给jdk核心类库使用。我们在平常的开发中无法通过该方法来获取 theUnsafe 对象。(可以通过万能的反射方式获取)
@CallerSensitive
public static Unsafe getUnsafe() {
Class var0 = Reflection.getCallerClass();
if (!VM.isSystemDomainLoader(var0.getClassLoader())) {
throw new SecurityException("Unsafe");
} else {
return theUnsafe;
}
}

// native方法,阻塞当前线程
public native void park(boolean var1, long var2);
// native方法,唤醒指定的线程
public native void unpark(Object var1);
}

关于可重入锁的Condition分析—-> 等待队列

// ReentrantLock
public Condition newCondition() {
return sync.newCondition();
}

// Sync
final ConditionObject newCondition() {
return new ConditionObject();
}

// AQS->ConditionObject
public class ConditionObject implements Condition, java.io.Serializable {
private static final long serialVersionUID = 1173984872572414699L;
private transient Node firstWaiter;
private transient Node lastWaiter;

public ConditionObject() { }

// 添加一个等待的线程
// 若是最后一个节点不为null,并且其 waitStatus 状态值不为 CONDITION。
private Node addConditionWaiter() {
Node t = lastWaiter;
// 添加之前先清理一番
if (t != null && t.waitStatus != Node.CONDITION) {
unlinkCancelledWaiters();
t = lastWaiter;
}
// 创建一个节点, 将其加入到同步队列的尾部
Node node = new Node(Thread.currentThread(), Node.CONDITION);
if (t == null) {
firstWaiter = node;
} else {
t.nextWaiter = node;
}
lastWaiter = node;
return node;
}

// 这个方法的目的就一个: 从等待队列中清除 waitStatus 状态值不为 CONDITION 的节点
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
Node trail = null;
// 在节点 t 不为 null 的情况下,不断的执行循环操作
while (t != null) {
// 首先保存下一个节点,然后判断当前节点
Node next = t.nextWaiter;
// 若是节点的 waitStatus 状态值不为 CONDITION,将节点 t 的 nextWaiter指向为null
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
// 这种情况是: 第一个节点的 waitStatus状态值已经不为 CONDITION 了,可能 next节点为等待节点,故先将 firstWaiter指向 next。若是当前的 trail不为null, 则 trail的nextWaiter也应该指向 next
if (trail == null) {
firstWaiter = next;
} else {
trail.nextWaiter = next;
}
// 这种情况是: 遍历到了最后一个节点,并且其 waitStatus 状态值不为 CONDITION,故需要在跳出循环之前将lastWaiter节点更新为 trail节点。
if (next == null) {
lastWaiter = trail;
}
// 若是节点的 waitStatus 状态值为 CONDITION
} else {
trail = t;
}
// 下一次循环遍历的节点
t = next;
}
}

/****************************************************/
final int fullyRelease(Node node) {
boolean failed = true;
try {
// 获取锁状态标识(0: 未上锁 >=1 上锁)
int savedState = getState();
// 释放成功,返回释放前 state 的值
if (release(savedState)) {
failed = false;
return savedState;
// 否则直接抛出异常
} else {
throw new IllegalMonitorStateException();
}
} finally {
// 若是操作失败,将当前节点的waitStatus状态值设置未CANCELLED
if (failed) {
node.waitStatus = Node.CANCELLED;
}
}
}

// 缩放锁->在调用await方法时,释放掉当前线程所持有的锁
public final boolean release(int arg) {
// tryRelease时 ReentrantLock的内部类Sync的方法,成功释放锁返回true,否则返回 false。
if (tryRelease(arg)) {
Node h = head;
// 当前线程已经进入到await状态,唤醒啦一个线程来获取锁
if (h != null && h.waitStatus != 0) {
unparkSuccessor(h);
}
return true;
}
// 其它情况返回 false
return false;
}

// 节点添加到同步队列和条件队列的区别(两点区别判断给定节点当前所处位置)
// 同步队列: 双向列表,节点有 prev 和 next 指针指向前驱节点和后继节点。nextWaiter 状态值为 null。
// 条件队列: 单向列表,节点有 nextWaiter 指针指向后继节点。waitStatus 状态值为 Node.CONDITION
// 若是节点已经在同步队列上,则返回 true
final boolean isOnSyncQueue(Node node) {
// 若是 waitStatus 为 Node.CONDITION,证明在条件队列,返回 false。
// 若不是在条件队列,但是节点的 prev 为 null,也返回 false。
if (node.waitStatus == Node.CONDITION || node.prev == null) {
return false;
}
// 若是节点的 next 指针不指向 null,直接返回 true
if (node.next != null) {
return true;
}
// 从同步队列的尾部找
return findNodeFromTail(node);
}
// 1. 若是在同步队列中找到了,返回 true。
// 2. 若是在同步队列中没有找到,返回 false。
private boolean findNodeFromTail(Node node) {
Node t = tail;
for (;;) {
// 若是找到的化,直接返回 true
if (t == node) {
return true;
}
// 已经找了一遍,但还是没有找到,返回 false
if (t == null) {
return false;
}
// 获取前一个节点判断
t = t.prev;
}
}

//
private int checkInterruptWhileWaiting(Node node) {
return Thread.interrupted() ?
(transferAfterCancelledWait(node) ? THROW_IE : REINTERRUPT) :
0;
}


// 关于await方法
// 1. 若是当前线程已经被中断,直接抛出异常,结束方法的运行。
// 2. 调用 addConditionWaiter 方法, 将当前的线程封装成为一个 Node 节点,添加到等待队列的尾部。
// 3. 调用 fullyRelease 方法,释放当前线程所获取到的锁。
// 4. while循环,调用 isOnSyncQueue 方法判断节点是否在同步队列,没在同步队列执行 while 循环体。挂起当前线程。
//
public final void await() throws InterruptedException {
if (Thread.interrupted()) {
throw new InterruptedException();
}
// 加入到等待队列
Node node = addConditionWaiter();
// 释放锁
int savedState = fullyRelease(node);
int interruptMode = 0;
// 线程没在同步队列。
while (!isOnSyncQueue(node)) {
// 挂起当前线程
LockSupport.park(this);
// 当前线程被唤醒时,执行。检查线程是否被打断,若是已经被打断,结束执行。
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0) {
break;
}
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE) {
interruptMode = REINTERRUPT;
}
if (node.nextWaiter != null) {
unlinkCancelledWaiters();
}
if (interruptMode != 0) {
reportInterruptAfterWait(interruptMode);
}
}

//
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 获取节点的前驱节点
final Node p = node.predecessor();
// 前驱节点为 head,尝试获取锁,并获取成功
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// 获取锁失败执行 park 操作。
if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt()) {
interrupted = true;
}
}
} finally {
if (failed) {
cancelAcquire(node);
}
}
}





// signal 方法分析
public final void signal() {
// 拥有锁的线程非当前线程,直接抛出异常
if (!isHeldExclusively()) {
throw new IllegalMonitorStateException();
}
// 获取到条件队列的第一个节点,对其执行 doSignal 操作。
Node first = firstWaiter;
if (first != null) {
doSignal(first);
}
}

// signalAll 方法分析
public final void signalAll() {
// 同 signal
if (!isHeldExclusively()) {
throw new IllegalMonitorStateException();
}
// 获取都条件队列的第一个节点,对其执行 doSignall 操作
Node first = firstWaiter;
if (first != null) {
doSignalAll(first);
}
}

// 操作是将给定的节点从条件队列转移至同步队列。若是操作失败,会去尝试给定节点的下一个节点,直到条件队列中已经没有节点了。
private void doSignal(Node first) {
do {
// 总会执行的操作: firstWaiter 指向 first 节点的 nextWaiter 节点。
if ( (firstWaiter = first.nextWaiter) == null) {
// 若是 firstWaiter 为 null 了,则 lastWaiter 也将指向 null。
lastWaiter = null;
}
// 下面的操作是将 first 节点添加到 同步队列,故将其 nextWaiter 属性值指向为 null。
first.nextWaiter = null;
// 若是将 first 节点从条件队列转移至同步队列失败并且 firstWaiter 不为 null。
} while (!transferForSignal(first) && (first = firstWaiter) != null);
}

// Node 节点 waitStatus 属性的几个状态值。
// static final int CANCELLED = 1; 表示节点已经被取消
// static final int SIGNAL = -1; 表示后面节点的线程需要被唤醒。
// static final int CONDITION = -2; 表示节点在条件队列上
// static final int PROPAGATE = -3; 关于共享锁的状态
// 0; 非以上值,取0
// Node 节点 nextWaiter 属性的几个状态值
// static final Node SHARED = new Node(); 标记节点在共享模式下等待
// static final Node EXCLUSIVE = null; 标记节点在排他模式下等待

// 操作: 将节点从条件队列转移至同步队列,操作成功返回 true。
final boolean transferForSignal(Node node) {
// case 操作尝试,失败返回 false。
if (!compareAndSetWaitStatus(node, Node.CONDITION, 0)) {
return false;
}
// 将该节点添加到同步队列的尾部,并返回该节点的前一个节点
Node p = enq(node);
// 获取返回节点的 waitStatus 状态值
int ws = p.waitStatus;
// ws 节点被取消
// ws 未被取消,尝试将其waitStatus状态值从 ws 设置为 SIGNAL失败
if (ws > 0 || !compareAndSetWaitStatus(p, ws, Node.SIGNAL)) {
// 唤醒该节点的线程
LockSupport.unpark(node.thread);
}
// 返回 true。
return true;
}

// 将节点插入到队列,必要时初始化。 返回值为 node 节点的前一个节点
private Node enq(final Node node) {
for (;;) {
Node t = tail;
// 同步队列为 null,初始化 head 和 tail。
if (t == null) {
if (compareAndSetHead(new Node())) {
tail = head;
}
} else {
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}

// doSignalAll, 唤醒条件队列上的所有线程
private void doSignalAll(Node first) {
// 清除条件队列
lastWaiter = firstWaiter = null;
// 循环操作,从第一个节点开始,将条件队列上的所有节点添加到同步队列
do {
// 保存下一个节点
Node next = first.nextWaiter;
// 清除 first 节点的 nextWaiter属性
first.nextWaiter = null;
// 将 first 节点转移至同不队列
transferForSignal(first);
// 更新 first 节点
first = next;
} while (first != null);
}
}

监听器模式

监听器模式

针对监听器模式,jdk提供了EventListener接口和EventObject类,分别定义事件监听器和事件对象。下面是通过扩展这两个接口实现一个简单的事件监听器模式。

/**
* @Author long
* @Date 2019/9/13 11:03
*/
public class App {
public static void main(String[] args) {
// 事件源
MyEventSource eventSource = new MyEventSource();
// 创建事件监听器->处理EventObject
StartEventListener startEventListener = new StartEventListener();
ClosedEventListener closedEventListener = new ClosedEventListener();
// 添加事件监听器
eventSource.addEventListener(startEventListener);
eventSource.addEventListener(closedEventListener);
// 创建事件对象
EventObject startEventObject = new EventObject("start");
EventObject closedEventObject = new EventObject("closed");
// 事件源->通知事件监听者来处理
eventSource.notifyListenerEvents(startEventObject);
eventSource.notifyListenerEvents(closedEventObject);
}
}

/**
* @Author long
* @Date 2019/9/13 11:00
* 扩展的监听器接口
*/
public interface MyEventListener extends EventListener {
/**
* 处理EventObject
* @param event
*/
void handleEvent(EventObject event);
}

/**
* @Author long
* @Date 2019/9/13 11:21
* 启动事件监听器
*/
public class StartEventListener implements MyEventListener {

@Override
public void handleEvent(EventObject event) {
Object source = event.getSource();
if (source.equals("start")) {
System.out.println("context has start!");
}
}
}

/**
* @Author long
* @Date 2019/9/13 11:24
* 关闭事件监听器
*/
public class ClosedEventListener implements MyEventListener {

@Override
public void handleEvent(EventObject event) {
Object source = event.getSource();
if (source.equals("closed")) {
System.out.println("context has closed!");
}
}
}

/**
* @Author long
* @Date 2019/9/13 11:03
* 事件源->添加 删除 通知
*/
public class MyEventSource {

/**
* 监听器列表
*/
private Vector<EventListener> listeners = new Vector<>();

/**
* 注册监听器
* @param eventListener
*/
public void addEventListener(EventListener eventListener) {
if (!listeners.contains(eventListener)) {
listeners.add(eventListener);
}
}

/**
* 移除监听器
* @param eventListener
*/
public void removeEventListener(EventListener eventListener) {
listeners.remove(eventListener);
}

/**
* 接收外部的事件->将事件交给事件监听者来处理
* @param event
*/
public void notifyListenerEvents(EventObject event) {
for (EventListener eventListener : listeners) {
((MyEventListener)eventListener).handleEvent(event);
}
}
}
jdk中监听器模式的实现

jdk针对监听器模式并未定义太多的实现,只是定义了一个EventListener接口和一个EventObject类,我们可以扩展EventListener接口来定义处理EventObject的方法。在EventObject中有一个属性Object:source,该属性可以在定义EventObject的时候,传入一些参数值。

public interface EventListener {

}
public class EventObject implements java.io.Serializable {

protected transient Object source;

public EventObject(Object source) {
if (source == null)
throw new IllegalArgumentException("null source");

this.source = source;
}

public Object getSource() {
return source;
}

public String toString() {
return getClass().getName() + "[source=" + source + "]";
}
}
spring中监听器模式的实现

在spring中定义了ApplicationListener接口和ApplicationEvent类,其中ApplicationListener接口实现了jdk中定义的EventListener接口,并定义了onApplicationEvent方法来处理事件,并且每个ApplicationListener只会处理特定的事件。ApplicationEvent类继承了jdk中定义的EventObject类,用以定义事件对象。

// 扩展的事件监听器接口->采用泛型
public interface ApplicationListener<E extends ApplicationEvent> extends EventListener {

void onApplicationEvent(E event);
}

// 扩展的EventObject
public abstract class ApplicationEvent extends EventObject {
private static final long serialVersionUID = 7099057708183571937L;

private final long timestamp;

public ApplicationEvent(Object source) {
super(source);
this.timestamp = System.currentTimeMillis();
}

public final long getTimestamp() {
return this.timestamp;
}

}
spring中监听器模式的使用
/**
* @Author long
* @Date 2019/9/13 11:46
*/
public class App {

public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 注册监听器
context.addApplicationListener(new ApplicationListener<MyApplicationEvent>() {
// 接收到事件
@Override
public void onApplicationEvent(MyApplicationEvent event) {
System.out.println(event.getSource());
}
});
context.refresh();
// 发布事件
context.publishEvent(new MyApplicationEvent("study spring!"));
}
}

class MyApplicationEvent extends ApplicationEvent{
MyApplicationEvent(Object source) {
super(source);
}
}

观察者模式

观察者模式

可以通过jdk中提供的Observable类和Observer接口来实现观察者模式。下面通过简单的会员订阅频道,然后频道定期的去给订阅的会员推送消息,展示jdk中观察者模式的使用。

/**
* @Author long
* @Date 2019/9/13 9:16
*/
public class App {
public static void main(String[] args) {
// 科技频道
TechnologyChannel technologyChannel = new TechnologyChannel();
technologyChannel.setTitle("科技频道");
// 用户
Members member1 = new Members();
Members member2 = new Members();
// 用户订阅该科技频道
technologyChannel.addObserver(member1);
technologyChannel.addObserver(member2);
// 给会员定时推送消息
String[] messages = {"华为", "小米", "苹果"};
Random random = new Random();
for (int i = 0; i < 10 ; i++) {
// 创建消息
NotifyMessage message = new NotifyMessage();
String id = UUID.randomUUID().toString();
message.setId(id);
message.setCreateTime(System.currentTimeMillis());
message.setTitle("手机");
message.setContent(messages[random.nextInt(3)] + "又出新机,赶快来订购吧!");
// 评到发送消息给订阅的会员
technologyChannel.setChanged();
technologyChannel.notifyObservers(message);
try {
TimeUnit.MILLISECONDS.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

/**
* @Author long
* @Date 2019/9/13 9:14
* 频道
*/
@Data
public class TechnologyChannel extends Observable {
private String title;

public synchronized void setChanged() {
super.setChanged();
}
}

/**
* @Author long
* @Date 2019/9/13 9:13
* 会员
*/
public class Members implements Observer {
@Override
public void update(Observable o, Object arg) {
if (o instanceof TechnologyChannel) {
TechnologyChannel channel = (TechnologyChannel)o;
String title = channel.getTitle();
NotifyMessage message = (NotifyMessage)arg;
System.out.println("channel:" + title);
System.out.println("message:" + message);
System.out.println("=======================");
}
}
}
/**
* @Author long
* @Date 2019/9/13 9:28
* 消息通知
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class NotifyMessage implements Serializable {

private String id;
private Long createTime;
private String title;
private String content;
}
jdk中观察者模式的实现
  1. 观察者(类似订阅模式中的订阅者)。jdk中定义了一个公共的接口Observer,里面定义了一个update方法,该方法可以接收被观察者对象和一个参数对象。我们可以通过实现该接口,重写update方法来实现观察者的逻辑。
  2. 被观察者(类似订阅模式中的被订阅者)。jdk中定义了一个类Observable,可以实现添加,移除,通知观察者。该类里面有两个属性boolean:changedVector:obs。当我们执行addObserver方法来添加观察者时,若是该观察者还未被加入到Vector:obs中,会将观察者加入到该集合。当我们执行notifyObservers方法来通知观察者时,只有changed属性为true时,才会依次调用观察者的update方法。若是该值为true,在调用观察者的update方法之前,又会将该值设置为false
public interface Observer {
void update(Observable o, Object arg);
}
public class Observable {
private boolean changed = false;
private Vector<Observer> obs;

public Observable() {
obs = new Vector<>();
}

// 添加观察者
public synchronized void addObserver(Observer o) {
if (o == null) {
throw new NullPointerException();
}
if (!obs.contains(o)) {
obs.addElement(o);
}
}

// 通知所有的观察者,可以传递一个参数
public void notifyObservers(Object arg) {
Object[] arrLocal;
synchronized (this) {
// 若是状态未变化,不做任何事情
if (!changed) {
return;
}
// 将Vector转化为一个数组
arrLocal = obs.toArray();
// 将changed设置为false
clearChanged();
}
// 循环遍历Observer数组,调用其update方法
for (int i = arrLocal.length-1; i>=0; i--)
((Observer)arrLocal[i]).update(this, arg);
}
}

分布式配置

分布式配置

相关产品
国内:Disconf(百度) Apollo(携程) Nacos(阿里)
国外: Spring-Cloud-Config Netfix Archaius

客户端
// 关于配置项的刷新->主动刷新(拉的模式)
1. 客户端可以通过接口 http://127.0.0.1:8082/actuator/refresh 来主动刷新配置(post方法) ,但是该接口的调用需要修改配置文件里面的值。
management.endpoint.refresh.enabled=true
2. 当配置项发生变化时,bean里面引用的配置项并未发生变化。需要使用 @RefreshScope 注解来标记,只有使用该注解标记的类,当配置项发生变化时,引用的配置项才会发生变化。
@RestController
@RefreshScope// (开关 阈值 文案等配置,其它配置可以重启服务器)
public class EchoController {

@Value("${my.name}")
private String myName = "jack-1";

@GetMapping("/myName")
public String getMyName() {
return myName;
}
}
3. 可以配置定时器来每隔指定的时间去主动刷新配置
@SpringBootApplication
@EnableScheduling // 开启定时任务
public class ConfigClientApp {
public static void main(String[] args) {
SpringApplication.run(ConfigClientApp.class, args);
}

// 定时刷新配置
private final ContextRefresher contextRefresher;

private final Environment environment;

public ConfigClientApp(ContextRefresher contextRefresher, Environment environment) {
this.contextRefresher = contextRefresher;
this.environment = environment;
}

// 配置定时器每隔5秒刷新一次配置项
@Scheduled(fixedRate = 5 * 1000, initialDelay = 3 * 1000)
public void autoRefresh() {
Set<String> updatedPropertyNames = contextRefresher.refresh();
updatedPropertyNames.forEach( propertyName ->
System.err.printf(
"[Thread :%s] 当前配置已更新,具体 Key:%s , Value : %s \n",
Thread.currentThread().getName(),
propertyName,
environment.getProperty(propertyName)
)
);
}
}
服务端
@EnableAutoConfiguration
@Configuration
@ComponentScan
// 激活配置管理服务器
@EnableConfigServer
public class ConfigServerApp {

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

/**
* 自定义配置实现,绕过git实现
* @return
*/
@Bean
public EnvironmentRepository environmentRepository() {
return (String application, String profile, String label) -> {
Environment environment = new Environment("default", profile);
List<PropertySource> propertySources = environment.getPropertySources();
Map<String, Object> source = new HashMap<String, Object>();
source.put("name", "微服务->long");
PropertySource propertySource = new PropertySource("map", source);
propertySources.add(propertySource);
return environment;
};
}
}
客户端流程分析
/*
1. 在客户端,我们可以配置形如: localhost:8080/{name}/{profiles}/{label} 去从服务端获取配置。
2. 在服务端是通过 EnvironmentController 类来对外提供服务的。
*/
@RestController
@RequestMapping(method = RequestMethod.GET, path = "${spring.cloud.config.server.prefix:}")
public class EnvironmentController {

@RequestMapping("/{name}/{profiles}/{label:.*}")
public Environment labelled(@PathVariable String name, @PathVariable String profiles,
@PathVariable String label) {
if (name != null && name.contains("(_)")) {
// "(_)" is uncommon in a git repo name, but "/" cannot be matched
// by Spring MVC
name = name.replace("(_)", "/");
}
if (label != null && label.contains("(_)")) {
// "(_)" is uncommon in a git branch name, but "/" cannot be matched
// by Spring MVC
label = label.replace("(_)", "/");
}
Environment environment = this.repository.findOne(name, profiles, label);
if (!this.acceptEmpty
&& (environment == null || environment.getPropertySources().isEmpty())) {
throw new EnvironmentNotFoundException("Profile Not found");
}
return environment;
}
}
服务端流程分析
/*
1. 在 @EnableConfigServer 注解中使用了 @Import 注解导入了配置类 ConfigServerConfiguration。
2. 在配置类 ConfigServerConfiguration 上面使用 @Configuration 注解表明该类是一个配置类,该配置类
会在上下文中创建一个类型为 ConfigServerConfiguration.Marker 的bean。
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(ConfigServerConfiguration.class)
public @interface EnableConfigServer {

}
@Configuration
public class ConfigServerConfiguration {
@Bean
public Marker enableConfigServerMarker() {
return new Marker();
}
class Marker {}
}
/*
1. ConfigServerAutoConfiguration 类上面使用了 @ConditionalOnBean 注解,只有当上下文中存在类型
为 ConfigServerConfiguration.Marker 的bean时,才会执行该配置类的流程(条件装配)。
2. 在该类中导入了一些配置类,EnvironmentRepositoryConfiguration 等这些类会根据条件判断创建相关的
bean。
*/
@Configuration // 配置类
@ConditionalOnBean(ConfigServerConfiguration.Marker.class) // 条件装配
@EnableConfigurationProperties(ConfigServerProperties.class)
@Import({ EnvironmentRepositoryConfiguration.class, CompositeConfiguration.class,
ResourceRepositoryConfiguration.class, ConfigServerEncryptionConfiguration.class,
ConfigServerMvcConfiguration.class })
public class ConfigServerAutoConfiguration {

}
/*
1. EnvironmentRepositoryConfiguration 通过 @Import 注解导入了一些相关的配置类。
JdbcRepositoryConfiguration GitRepositoryConfiguration 分别时基于jdbc和git实现配置
的仓储。
2. GitRepositoryConfiguration 继承啦 DefaultRepositoryConfiguration 类,属于默认实现。
3. 在 DefaultRepositoryConfiguration 类中 通过 @ConditionalOnMissingBean 注解表明当前
上下文中若是没有 EnvironmentRepository 类型的bean存在时,会创建一个类型为
MultipleJGitEnvironmentRepository 的bean
*/
// EnvironmentRepositoryConfiguration 配置
@Configuration
@EnableConfigurationProperties({ SvnKitEnvironmentProperties.class,
CredhubEnvironmentProperties.class, JdbcEnvironmentProperties.class,
NativeEnvironmentProperties.class, VaultEnvironmentProperties.class })
@Import({ CompositeRepositoryConfiguration.class, JdbcRepositoryConfiguration.class,
VaultConfiguration.class, VaultRepositoryConfiguration.class,
CredhubConfiguration.class, CredhubRepositoryConfiguration.class,
SvnRepositoryConfiguration.class, NativeRepositoryConfiguration.class,
GitRepositoryConfiguration.class, DefaultRepositoryConfiguration.class })
public class EnvironmentRepositoryConfiguration {

}

// GitRepositoryConfiguration git实现的配置,继承了 DefaultRepositoryConfiguration 默认实现
@Configuration
@Profile("git")
class GitRepositoryConfiguration extends DefaultRepositoryConfiguration {

}
// JdbcRepositoryConfiguration jdbc实现的配置
@Configuration
@Profile("jdbc")
@ConditionalOnClass(JdbcTemplate.class)
class JdbcRepositoryConfiguration {
@Bean
@ConditionalOnBean(JdbcTemplate.class)
public JdbcEnvironmentRepository jdbcEnvironmentRepository(
JdbcEnvironmentRepositoryFactory factory,
JdbcEnvironmentProperties environmentProperties) {
return factory.build(environmentProperties);
}
}

@Configuration
@ConditionalOnMissingBean(value = EnvironmentRepository.class, search = SearchStrategy.CURRENT)
class DefaultRepositoryConfiguration {
@Bean
public MultipleJGitEnvironmentRepository defaultEnvironmentRepository(
MultipleJGitEnvironmentRepositoryFactory gitEnvironmentRepositoryFactory,
MultipleJGitEnvironmentProperties environmentProperties) throws Exception {
return gitEnvironmentRepositoryFactory.build(environmentProperties);
}
}
/*
到此,还有一个问题,那就是 ConfigServerAutoConfiguration 时如何加载的,通过相关jar包里面的
spring.factories 文件可以看到 ConfigServerAutoConfiguration 被 EnableAutoConfiguration
通过spring的spi加载。
*/
# Autoconfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.cloud.config.server.config.ConfigServerAutoConfiguration,\
org.springframework.cloud.config.server.config.EncryptionAutoConfiguration