跳转至
本文阅读量

1. spring 包名

spring-core spring-beans spring-context spring-expression spring-aop spring-jcl spring-test

spring-web spring-webmvc

spring-boot spring-boot-autoconfigure spring-boot-devtools spring-boot-starter spring-boot-starter-logging spring-boot-starter-test

org.springframework.core org.springframework.beans org.springframework.beans.factory org.springframework.context

BeanFactory 和 ApplicationContext

BeanFactory => 是Bean,Context 等的父类 FactoryBean => 是工厂方法,提供 getObject 的能力

Spring 的三类配置方式 XML-based 配置 Annotation-based configuration: Spring 2.5 Java-based configuration: Starting with Spring 3.0,

Annotation-based 配置 ConfigurationClassPostProcessor AutowiredAnnotationBeanPostProcessor CommonAnnotationBeanPostProcessor PersistenceAnnotationBeanPostProcessor EventListenerMethodProcessor

LifecycleProcessor

@Required @Autowired @Primary @Qualifier

@Resource @Value @PostConstruct @PreDestroy

@Component

Spring Annotation Programming Model https://github.com/spring-projects/spring-framework/wiki/Spring-Annotation-Programming-Model ⧉

Java-based 配置 @Bean <= 核心 @Configuration <= 核心 @PropertySource @DependsOn @Import AnnotationConfigApplicationContext

BeanDefinition BeanFactory ApplicationContext DefaultListableBeanFactory registerSingleton registerBeanDefinition

BeanDefinition Class Instantiating Beans Instantiation with a Constructor Instantiation with a Static Factory Method Instantiation by Using an Instance Factory Method Name Naming Beans Scope Bean Scopes Constructor arguments Dependency Injection Properties Dependency Injection Autowiring mode Autowiring Collaborators Lazy initialization mode Lazy-initialized Beans Initialization method Initialization Callbacks Destruction method Destruction Callbacks

Container Extension Points BeanPostProcessor Customizing Configuration Metadata BeanFactoryPostProcessor

PropertySourcesPlaceholderConfigurer

BeanNameGenerator

AnnotatedBeanDefinition

@ComponentScan - basePackages - nameGenerator - scopeResolver - includeFilters - excludeFilters - lazyInit

By default, beans defined with Java configuration that have a public close or shutdown method are automatically enlisted with a destruction callback. If you have a public close or shutdown method and you do not wish for it to be called when the container shuts down, you can add @Bean(destroyMethod="") to your bean definition to disable the default (inferred) mode.

@SpringBootApplication

ImportBeanDefinitionRegistrar

ClassPathScanningCandidateComponentProvider findCandidateComponents

AnnotationMetadata getAnnotationAttributes

AnnotatedElement

MergedAnnotations TypeMappedAnnotations StandardAnnotationMetadata

SearchStrategy

AnnotationTypeFilter AbstractTypeHierarchyTraversingFilter TypeFilter

BeanDefinition AnnotatedBeanDefinition

ConfigurationClass importBeanDefinitionRegistrars

FeignClientFactoryBean

TypeDescriptor 貌似 Spring 形容范型类型的 可以详见 ConversionService

MultiValueMap body = new LinkedMultiValueMap<>(); body.add("files", getTestFile()); body.add("files", getTestFile()); body.add("files", getTestFile());

HttpEntity> requestEntity = new HttpEntity<>(body, headers);

String serverUrl = "http://localhost:8082/spring-rest/fileserver/multiplefileupload/ ⧉";

RestTemplate restTemplate = new RestTemplate(); ResponseEntity response = restTemplate .postForEntity(serverUrl, requestEntity, String.class);

Bean factory implementations should support the standard bean lifecycle interfaces as far as possible. The full set of initialization methods and their standard order is:

BeanNameAware's setBeanName BeanClassLoaderAware's setBeanClassLoader BeanFactoryAware's setBeanFactory EnvironmentAware's setEnvironment EmbeddedValueResolverAware's setEmbeddedValueResolver ResourceLoaderAware's setResourceLoader (only applicable when running in an application context) ApplicationEventPublisherAware's setApplicationEventPublisher (only applicable when running in an application context) MessageSourceAware's setMessageSource (only applicable when running in an application context) ApplicationContextAware's setApplicationContext (only applicable when running in an application context) ServletContextAware's setServletContext (only applicable when running in a web application context) postProcessBeforeInitialization methods of BeanPostProcessors InitializingBean's afterPropertiesSet a custom init-method definition postProcessAfterInitialization methods of BeanPostProcessors

ConfigurationClassPostProcessor
AutowiredAnnotationBeanPostProcessor
CommonAnnotationBeanPostProcessor
PersistenceAnnotationBeanPostProcessor
EventListenerMethodProcessor
RequiredAnnotationBeanPostProcessor

On shutdown of a bean factory, the following lifecycle methods apply:

postProcessBeforeDestruction methods of DestructionAwareBeanPostProcessors DisposableBean's destroy a custom destroy-method definition

BeanFactory => ApplictionContext 增加了如下功能 Easier integration with Spring’s AOP features Message resource handling (for use in internationalization) Event publication Application-layer specific contexts such as the WebApplicationContext for use in web applications. 多层级 ApplicationContext

CommonAnnotationBeanPostProcessor

BeanPostProcessor ConversionService DefaultFormattingConversionService

从 Spring 2.5 开始,可以有三个方法控制 lifecycle - 通过 InitializingBean 和 DisposableBean 回调接口 - 通过 init() 和 destroy() 方法 - 通过 @PostConstruct 和 @PreDestroy 注解

多种 lifecycle 机制存在时的调用顺序 初始化时 Methods annotated with @PostConstruct afterPropertiesSet() as defined by the InitializingBean callback interface A custom configured init() method 关闭时 Methods annotated with @PreDestroy destroy() as defined by the DisposableBean callback interface A custom configured destroy() method

JSR 330 注解 @Inject @Named @ManagedBean

JSR 330 和 Spring 之间注解之间的区分 @Autowired <> @Inject @Component <> @Named / @ManagedBean @Scope("singleton") <> @Singleton @Qualifier <> @Qualifier / @Named @Value <> NA @Requred <> NA @Lazy <> NA ObjectFactory <> Provider

构造函数注入 如果 Bean 只有一个构造函数,则不需要在构造函数上通过 @Autowired 来指定;但如果有多个构造函数时,则需要通过 @Autowired 来指定

Full @Configuration vs “lite” @Bean mode? ???? 后续搞清楚

@Bean 可以搭配 @Configuration 或 @Component 使用

constructor-based dependency injection

@Configuration
public class AppConfig {

    @Bean
    public TransferService transferService(AccountRepository accountRepository) {
        return new TransferServiceImpl(accountRepository);
    }
}

1.6. Customizing the Nature of a Bean InitializingBean afterPropertiesSet DisposableBean destroy

可以通过 @Profile 指定某个配置或Bean 的条件生效

@Configuration
public class AppConfig {

    @Bean("dataSource")
    @Profile("development") 
    public DataSource standaloneDataSource() {
        return new EmbeddedDatabaseBuilder()
            .setType(EmbeddedDatabaseType.HSQL)
            .addScript("classpath:com/bank/config/sql/schema.sql")
            .addScript("classpath:com/bank/config/sql/test-data.sql")
            .build();
    }

    @Bean("dataSource")
    @Profile("production") 
    public DataSource jndiDataSource() throws Exception {
        Context ctx = new InitialContext();
        return (DataSource) ctx.lookup("java:comp/env/jdbc/datasource");
    }
}

Spring 引入的各种 SPI - Converter SPI - Formatter SPI - FormatterRegistrar SPI

ConverterFactory GenericConverter ConditionalConverter ConditionalGenericConverter

ConversionService ConverterRegistry GenericConversionService

ConversionServiceFactory

FormatterRegistry FormattingConversionService

1.1 数据验证方面的类

  • MethodValidationPostProcessor
  • LocalValidatorFactoryBean
  • ConstraintValidator
  • @Constraint
  • SpringConstraintValidatorFactory
  • org.springframework.validation.Validator

  • DataBinder

  • BindingResult

2. SpEL

SpEL 支持以下操作 The expression language supports the following functionality: Literal expressions Boolean and relational operators Regular expressions Class expressions Accessing properties, arrays, lists, and maps Method invocation Relational operators Assignment Calling constructors Bean references Array construction Inline lists Inline maps Ternary operator Variables User-defined functions Collection projection Collection selection Templated expressions

核心类 ExpressionParser SpelExpressionParser SpelParserConfiguration Expression getValue EvaluationContext SimpleEvaluationContext 没有如下相关操作: Java type references, constructors, and bean references By default, the create() static factory method enables only read access to properties 可以通过 Builder 进行配置 StandardEvaluationContext

SpEL 是范型感知的

class Simple {
    public List<Boolean> booleanList = new ArrayList<Boolean>();
}

Simple simple = new Simple();
simple.booleanList.add(true);

EvaluationContext context = SimpleEvaluationContext.forReadOnlyDataBinding().build();

// "false" is passed in here as a String. SpEL and the conversion service
// will recognize that it needs to be a Boolean and convert it accordingly.
parser.parseExpression("booleanList[0]").setValue(context, simple, "false");

// b is false
Boolean b = simple.booleanList.get(0);

Compiler Configuration 三种模式: OFF, IMMEDIATE, MIXED

通过 # 引用变量, 通过 @ 引用 Bean, 通过 T 引用类, 通过 $ 引用 通过 # 引用 #{systemProperties['pop3.port']} To access a factory bean itself, you should instead prefix the bean name with an & symbol

通过 #newName 引用变量

this

root

name?:"1234" => name != null ? name : "1234" name = placeOfBirth?.city => if placeOfBirth.city != null placeOfBirth.city else null, 不抛异常

Collection Selection .?[selectionExpression] 所有满足selectionExpression的 ^[selectionExpression] 第一个满足selectionExpression的 .$[selectionExpression] 最后一个满足selectionExpression的

List<Inventor> list = (List<Inventor>) parser.parseExpression(
        "members.?[nationality == 'Serbian']").getValue(societyContext);
Map newMap = parser.parseExpression("map.?[value<27]").getValue();

Collection Projection

.![projectionExpression]

// returns ['Smiljan', 'Idvor' ]
List placesOfBirth = (List)parser.parseExpression("members.![placeOfBirth.city]");

4.3.18. Expression templating

String randomPhrase = parser.parseExpression(
        "random number is #{T(java.lang.Math).random()}",
        new TemplateParserContext()).getValue(String.class);

5. AOP

通过 and 进行 AOP 表达式组合

6. 核心类或接口

Pointcut Advisor TargetSource HotSwappableTargetSource PrototypeTargetSource ThreadLocalTargetSource DefaultAdvisorAutoProxyCreator

AdvisorAdapter MethodBeforeAdviceAdapter AfterReturningAdviceAdapter ThrowsAdviceAdapter

Advice Interceptor MethodInterceptor MethodBeforeAdviceInterceptor ThrowsAdviceInterceptor AfterReturningAdviceInterceptor AfterReturningAdviceAdapter

  • DefaultSingletonBeanRegistry

7. 8. Data Buffers and Codecs

  • DataBufferFactory abstracts the creation of a data buffer.
  • DataBuffer represents a byte buffer, which may be pooled.
  • DataBufferUtils offers utility methods for data buffers.
  • Codecs decode or encode data buffer streams into higher level objects.

7.1 xxxAware

  • BeanNameAware
  • BeanClassLoaderAware
  • BeanFactoryAware

  • ApplicationContextAware

  • ApplicationEventPublisherAware
  • EmbeddedValueResolverAware
  • EnvironmentAware
  • ResourceLoaderAware
  • ImportAware
  • LoadTimeWeaverAware
  • NotificationPublisherAware
The org.springframework.context.ApplicationContext interface represents the Spring IoC container and is responsible for instantiating, configuring, and assembling the beans. The container gets its instructions on what objects to instantiate, configure, and assemble by reading configuration metadata. The configuration metadata is represented in XML, Java annotations, or Java code. 

7.2 @Autowire 和 @Resource 的区别

@Autowire @Resource 备注
Spring 定义的注解 JSR 定义的注解
默认按照类型注入 默认按照名字注入
可以作用到构造函数、变量、setter函数 不支持作用到构造函数
找不到对应Bean时报错 可能为空 @Autowire可以通过两种方式注入可能为空的 Bean
  • CommonAnnotationBeanPostProcessor
  • CustomAutowireConfigurer

7.1 Spring 扩展机制

  • CustomAutowireConfigurer
  • AutowiredAnnotationBeanPostProcessor

7.2 Meno

7.2.1 @Configuration+@Bean 是full模式, 如果仅是 @Bean 是 lite 模式

7.3 参考

7.4 TODO

  • AnnotatedBeanDefinitionReader 如何读取的 AnnotatedBean 的定义
  • 什么是 ScopedProxyMode ,影响是什么?
This method of declaring inter-bean dependencies works only when the @Bean method 
is declared within a @Configuration class. You cannot declare inter-bean dependencies 
by using plain @Component classes.
  • Lookup Method Injection

    • 当一个 singleton-scoped 的 bean 依赖 prototype-scoped 的 bean 时使用
  • DataBinder

  • BeanWrapper
  • PropertyEditorSupport
  • PropertyEditor
  • Validator

  • Converter

  • GenericConverter
  • ConditionalGenericConverter
  • ConverterFactory
  • ConversionService
  • ConverterRegistry *
  • ConversionServiceFactory
  • DataBinder

7.5 Transaction (事务)

事务包括 Global Transaction (分布式事务)Local Transaction(本地事务) * Global Transaction 可以作用到多个资源上 * Local Transaction 则仅作用到 JDBC Connection 上

7.5.1 一些关键类

  • TransactionManager
  • PlatformTransactionManager
  • ReactiveTransactionManager
  • TransactionDefinition

  • Transaction Propagation ⧉

    • PROPAGATION_REQUIRED: 内部新起逻辑Transaction,inner 的逻辑 Transaction 的回滚会影响外部的 Transaction
    • PROPAGATION_SUPPORTS
    • PROPAGATION_MANDATORY
    • PROPAGATION_REQUIRES_NEW: 新建物理 Transaction,外部 Transaction 挂起
    • PROPAGATION_NOT_SUPPORTED
    • PROPAGATION_NEVER
    • PROPAGATION_NESTED: 一个物理 Transaction,多个 Savepoints,仅支持 JDBC 类型的 resource transactions

7.5.2 Isolation Level

  • ISOLATION_DEFAULT
  • ISOLATION_READ_UNCOMMITTED
  • ISOLATION_READ_COMMITTED
  • ISOLATION_REPEATABLE_READ
  • ISOLATION_SERIALIZABLE

Transaction 默认捕获的必须是 RuntimeException 及其子类;但如果通过 rollbackFor 显示指定,则以指定的规则为准

How to add plugins to the Docker image?

The Spring team recommends that you annotate only concrete classes (and methods of concrete classes) with the @Transactional annotation, as opposed to annotating interfaces. You certainly can place the @Transactional annotation on an interface (or an interface method), but this works only as you would expect it to if you use interface-based proxies. The fact that Java annotations are not inherited from interfaces means that, if you use class-based proxies (proxy-target-class="true") or the weaving-based aspect (mode="aspectj"), the transaction settings are not recognized by the proxying and weaving infrastructure, and the object is not wrapped in a transactional proxy.

  • @Transactional 最好作用在具体类上,而不是 Interface
  • @Transactional 服务内部调用时不生效

7.5.3 Multiple Transaction Managers with @Transactional

public class TransactionalService {

    @Transactional("order")
    public void setSomething(String name) { ... }

    @Transactional("account")
    public void doSomething() { ... }

    @Transactional("reactive-account")
    public Mono<Void> doSomethingReactive() { ... }
}

7.5.4 Transaction-bound Events

7.5.5 Advice Mode (Proxy Mode)

  • proxy:
  • aspectj:

  • Interface-Based Proxy

  • Class-Based Proxy
  • Weaving-Base Aspect

beanNamesForTypeIncludingAncestors

MappingJacksonValue

@RestController
public class UserController {

    @GetMapping("/user")
    public MappingJacksonValue getUser() {
        User user = new User("eric", "7!jd#h23");
        MappingJacksonValue value = new MappingJacksonValue(user);
        value.setSerializationView(User.WithoutPasswordView.class);
        return value;
    }
}

7.6 Data Access

7.6.1 创建 EntityManagerFactory 的三种方式

  • 使用 LocalEntityManagerFactoryBean
  • 从 JNDI 中获取 EntityManagerFactory
  • 使用 LocalContainerEntityManagerFactoryBean

7.7 待整理

  • ClassFileTransformer
  • LoadTimeWeaver

7.8 Spring 扩展点

  • InitializingBean 中的 afterPropertiesSet() 方法
  • DisposableBean 中的 destroy() 方法
  • WebApplicationInitializer 中的 onStartup() 方法
  • 实现 WebMvcConfigurer 接口

  • @Controller 中通过 @InitBinder 注解

  • WebMvcAutoConfiguration
  • ApplicationContextInitializer 中的 initialize() 方法

7.9 如何实现一个新的 Formater

7.9.1 背景了解,什么是 Formater

package org.springframework.format;

public interface Formatter<T> extends Printer<T>, Parser<T> {
}

public interface Printer<T> {
    String print(T fieldValue, Locale locale);
}

public interface Parser<T> {
    T parse(String clientValue, Locale locale) throws ParseException;
}

7.9.2 如何实现 Formatter

通过 AnnotationFormatterFactory

package org.springframework.format;

public interface AnnotationFormatterFactory<A extends Annotation> {

    Set<Class<?>> getFieldTypes();

    Printer<?> getPrinter(A annotation, Class<?> fieldType);

    Parser<?> getParser(A annotation, Class<?> fieldType);
}

7.9.3 示例

public final class NumberFormatAnnotationFormatterFactory
        implements AnnotationFormatterFactory<NumberFormat> {

    private static final Set<Class<?>> FIELD_TYPES = Set.of(Short.class,
            Integer.class, Long.class, Float.class, Double.class,
            BigDecimal.class, BigInteger.class);

    public Set<Class<?>> getFieldTypes() {
        return FIELD_TYPES;
    }

    public Printer<Number> getPrinter(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterFrom(annotation, fieldType);
    }

    public Parser<Number> getParser(NumberFormat annotation, Class<?> fieldType) {
        return configureFormatterFrom(annotation, fieldType);
    }

    private Formatter<Number> configureFormatterFrom(NumberFormat annotation, Class<?> fieldType) {
        if (!annotation.pattern().isEmpty()) {
            return new NumberStyleFormatter(annotation.pattern());
        }
        // else
        return switch(annotation.style()) {
            case Style.PERCENT -> new PercentStyleFormatter();
            case Style.CURRENCY -> new CurrencyStyleFormatter();
            default -> new NumberStyleFormatter();
        };
    }
}

public class MyModel {

    @NumberFormat(style=Style.CURRENCY)
    private BigDecimal decimal;
}