前言:

Spring4推出了@Conditional注解,方便程序根据当前环境或者容器情况来动态注入bean,对@Conditional注解不熟悉的朋友可移步至 Spring @Conditional注解 详细讲解及示例 这篇博客进行学习。

继@Conditional注解后,又基于此注解推出了很多派生注解,比如@ConditionalOnBean、@ConditionalOnMissingBean、@ConditionalOnExpression、@ConditionalOnClass......动态注入bean变得更方便了。本篇将讲解@ConditionalOnBean注解。

配置类中有两个Computer类的bean,一个是笔记本电脑,一个是备用电脑。如果当前容器中已经有电脑bean了,就不注入备用电脑,如果没有,则注入备用电脑,这里需要使用到@ConditionalOnMissingBean。

    1. @Configuration
      1. public class BeanConfig {
          1. @Bean(name = "notebookPC")
            1. public Computer computer1(){
              1. return new Computer("笔记本电脑");
                1. }
                    1. @ConditionalOnMissingBean(Computer.class)
                      1. @Bean("reservePC")
                        1. public Computer computer2(){
                          1. return new Computer("备用电脑");
                            1. }
                              1. }
                            1.  

                            这个注解就实现了功能,这个@ConditionalOnMissingBean为我们做了什么呢?我们来一探究竟.。

                            一探究竟:

                            首先,来看@ConditionalOnMissingBean的声明:

                              1. //可以标注在类和方法上
                                1. @Target({ElementType.TYPE, ElementType.METHOD})
                                  1. @Retention(RetentionPolicy.RUNTIME)
                                    1. @Documented
                                      1. //使用了@Conditional注解,条件类是OnBeanCondition
                                        1. @Conditional({OnBeanCondition.class})
                                          1. public @interface ConditionalOnMissingBean {
                                            1. Class<?>[] value() default {};
                                                1. String[] type() default {};
                                                    1. Class<?>[] ignored() default {};
                                                        1. String[] ignoredType() default {};
                                                            1. Class<? extends Annotation>[] annotation() default {};
                                                                1. String[] name() default {};
                                                                    1. SearchStrategy search() default SearchStrategy.ALL;
                                                                      1. }
                                                                    1.  

                                                                    这时候,我们就看到了我们熟悉的@Conditional注解,OnBeanCondition作为条件类。

                                                                    OnBeanCondition类的声明:

                                                                      1. //定义带注释的组件的排序顺序,2147483647即为默认值
                                                                        1. @Order(2147483647)
                                                                          1. class OnBeanCondition extends SpringBootCondition implements ConfigurationCondition {
                                                                        1.  

                                                                        它继承了SpringBootCondition类,OnBeanCondition类中没有matches方法,而SpringBootCondition类中有实现matches方法。OnBeanCondition还实现了ConfigurationCondition,ConfigurationCondition接口不熟悉的读者可以到Spring ConfigurationCondition接口详解 了解接口。OnBeanCondition类重写了getConfigurationPhase()方法,表示在注册bean的时候注解生效:

                                                                          1. public ConfigurationPhase getConfigurationPhase() {
                                                                            1. return ConfigurationPhase.REGISTER_BEAN;
                                                                              1. }
                                                                            1.  

                                                                            就从matches方法开始:

                                                                              1. //SpringBootCondition类中的matches方法
                                                                                1. public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
                                                                                  1. //获取当前的类名或者方法名(由标注的位置决定)
                                                                                    1. String classOrMethodName = getClassOrMethodName(metadata);
                                                                                        1. try {
                                                                                          1. //关键代码:这里就会判断出结果
                                                                                            1. ConditionOutcome outcome = this.getMatchOutcome(context, metadata);
                                                                                              1. //存入日志
                                                                                                1. this.logOutcome(classOrMethodName, outcome);
                                                                                                  1. //存入记录
                                                                                                    1. this.recordEvaluation(context, classOrMethodName, outcome);
                                                                                                      1. //最后返回ConditionOutcome的isMatch就是返回boolean类型结果
                                                                                                        1. return outcome.isMatch();
                                                                                                          1. } catch (NoClassDefFoundError var5) {
                                                                                                            1. throw new IllegalStateException("Could not evaluate condition on " + classOrMethodName + " due to " + var5.getMessage() + " not found. Make sure your own configuration does not rely on that class. This can also happen if you are @ComponentScanning a springframework package (e.g. if you put a @ComponentScan in the default package by mistake)", var5);
                                                                                                              1. } catch (RuntimeException var6) {
                                                                                                                1. throw new IllegalStateException("Error processing condition on " + this.getName(metadata), var6);
                                                                                                                  1. }
                                                                                                                    1. }
                                                                                                                  1.  

                                                                                                                  关键代码在OnBeanCondition的getMatchOutcome方法上:

                                                                                                                    1. /**
                                                                                                                      1. * 获得判断结果的方法,ConditionOutcome类中存着boolean类型的结果
                                                                                                                        1. */
                                                                                                                          1. public ConditionOutcome getMatchOutcome(ConditionContext context, AnnotatedTypeMetadata metadata) {
                                                                                                                            1. //返回一个新的ConditionMessage
                                                                                                                              1. ConditionMessage matchMessage = ConditionMessage.empty();
                                                                                                                                1. OnBeanCondition.BeanSearchSpec spec;
                                                                                                                                  1. List matching;
                                                                                                                                    1. //这是metadata会调用isAnnotated方法判断当前标注的注解是不是ConditionalOnMissingBean
                                                                                                                                      1. //其实@ConditionalOnBean、@ConditionalOnMissingBean和@ConditionalOnSingleCandidate都是使用这个条件类,所以这里做判断
                                                                                                                                        1. if (metadata.isAnnotated(ConditionalOnBean.class.getName())) {
                                                                                                                                          1. spec = new OnBeanCondition.BeanSearchSpec(context, metadata, ConditionalOnBean.class);
                                                                                                                                            1. matching = this.getMatchingBeans(context, spec);
                                                                                                                                              1. if (matching.isEmpty()) {
                                                                                                                                                1. return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnBean.class, new Object[]{spec}).didNotFind("any beans").atAll());
                                                                                                                                                  1. }
                                                                                                                                                      1. matchMessage = matchMessage.andCondition(ConditionalOnBean.class, new Object[]{spec}).found("bean", "beans").items(Style.QUOTE, matching);
                                                                                                                                                        1. }
                                                                                                                                                            1. if (metadata.isAnnotated(ConditionalOnSingleCandidate.class.getName())) {
                                                                                                                                                              1. OnBeanCondition.BeanSearchSpec spec = new OnBeanCondition.SingleCandidateBeanSearchSpec(context, metadata, ConditionalOnSingleCandidate.class);
                                                                                                                                                                1. matching = this.getMatchingBeans(context, spec);
                                                                                                                                                                  1. if (matching.isEmpty()) {
                                                                                                                                                                    1. return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, new Object[]{spec}).didNotFind("any beans").atAll());
                                                                                                                                                                      1. }
                                                                                                                                                                          1. if (!this.hasSingleAutowireCandidate(context.getBeanFactory(), matching, spec.getStrategy() == SearchStrategy.ALL)) {
                                                                                                                                                                            1. return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnSingleCandidate.class, new Object[]{spec}).didNotFind("a primary bean from beans").items(Style.QUOTE, matching));
                                                                                                                                                                              1. }
                                                                                                                                                                                  1. matchMessage = matchMessage.andCondition(ConditionalOnSingleCandidate.class, new Object[]{spec}).found("a primary bean from beans").items(Style.QUOTE, matching);
                                                                                                                                                                                    1. }
                                                                                                                                                                                        1. //如果当前注入的bean是@ConditionalOnMissingBean
                                                                                                                                                                                          1. if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {
                                                                                                                                                                                            1. //返回一个spec(说明),这里的spec规定了搜索的内容,比如搜索策略、需要搜索的类名......
                                                                                                                                                                                              1. spec = new OnBeanCondition.BeanSearchSpec(context, metadata, ConditionalOnMissingBean.class);
                                                                                                                                                                                                1. //主要的搜索实现在这个方法里,最后返回一个list
                                                                                                                                                                                                  1. matching = this.getMatchingBeans(context, spec);
                                                                                                                                                                                                    1. //判断搜索出来的结果
                                                                                                                                                                                                      1. if (!matching.isEmpty()) {
                                                                                                                                                                                                        1. return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingBean.class, new Object[]{spec}).found("bean", "beans").items(Style.QUOTE, matching));
                                                                                                                                                                                                          1. }
                                                                                                                                                                                                              1. matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class, new Object[]{spec}).didNotFind("any beans").atAll();
                                                                                                                                                                                                                1. }
                                                                                                                                                                                                                    1. return ConditionOutcome.match(matchMessage);
                                                                                                                                                                                                                      1. }
                                                                                                                                                                                                                    1.  

                                                                                                                                                                                                                    spec = new OnBeanCondition.BeanSearchSpec(context, metadata, ConditionalOnBean.class);

                                                                                                                                                                                                                    这句中,相当于从内部类中将标注@ConditionalOnMissingBean注解时的属性都取出来:

                                                                                                                                                                                                                      1. BeanSearchSpec(ConditionContext context, AnnotatedTypeMetadata metadata, Class<?> annotationType) {
                                                                                                                                                                                                                        1. this.annotationType = annotationType;
                                                                                                                                                                                                                          1. MultiValueMap<String, Object> attributes = metadata.getAllAnnotationAttributes(annotationType.getName(), true);
                                                                                                                                                                                                                            1. //将attributes这个map中的数据放到对应的list成员变量中
                                                                                                                                                                                                                              1. this.collect(attributes, "name", this.names);
                                                                                                                                                                                                                                1. this.collect(attributes, "value", this.types);
                                                                                                                                                                                                                                  1. this.collect(attributes, "type", this.types);
                                                                                                                                                                                                                                    1. this.collect(attributes, "annotation", this.annotations);
                                                                                                                                                                                                                                      1. this.collect(attributes, "ignored", this.ignoredTypes);
                                                                                                                                                                                                                                        1. this.collect(attributes, "ignoredType", this.ignoredTypes);
                                                                                                                                                                                                                                          1. this.strategy = (SearchStrategy)metadata.getAnnotationAttributes(annotationType.getName()).get("search");
                                                                                                                                                                                                                                            1. OnBeanCondition.BeanTypeDeductionException deductionException = null;
                                                                                                                                                                                                                                                1. try {
                                                                                                                                                                                                                                                  1. if (this.types.isEmpty() && this.names.isEmpty()) {
                                                                                                                                                                                                                                                    1. this.addDeducedBeanType(context, metadata, this.types);
                                                                                                                                                                                                                                                      1. }
                                                                                                                                                                                                                                                        1. } catch (OnBeanCondition.BeanTypeDeductionException var7) {
                                                                                                                                                                                                                                                          1. deductionException = var7;
                                                                                                                                                                                                                                                            1. }
                                                                                                                                                                                                                                                                1. this.validate(deductionException);
                                                                                                                                                                                                                                                                  1. }
                                                                                                                                                                                                                                                                      1. //验证的方法
                                                                                                                                                                                                                                                                        1. protected void validate(OnBeanCondition.BeanTypeDeductionException ex) {
                                                                                                                                                                                                                                                                          1. if (!this.hasAtLeastOne(this.types, this.names, this.annotations)) {
                                                                                                                                                                                                                                                                            1. String message = this.annotationName() + " did not specify a bean using type, name or annotation";
                                                                                                                                                                                                                                                                              1. if (ex == null) {
                                                                                                                                                                                                                                                                                1. throw new IllegalStateException(message);
                                                                                                                                                                                                                                                                                  1. } else {
                                                                                                                                                                                                                                                                                    1. throw new IllegalStateException(message + " and the attempt to deduce the bean's type failed", ex);
                                                                                                                                                                                                                                                                                      1. }
                                                                                                                                                                                                                                                                                        1. }
                                                                                                                                                                                                                                                                                          1. }
                                                                                                                                                                                                                                                                                        1.  

                                                                                                                                                                                                                                                                                        看一下OnBeanCondition类中的getMatchingBeans方法,里面有用到搜索策略,详见搜索策略介绍

                                                                                                                                                                                                                                                                                          1. private List<String> getMatchingBeans(ConditionContext context, OnBeanCondition.BeanSearchSpec beans) {
                                                                                                                                                                                                                                                                                            1. //获得当前bean工厂
                                                                                                                                                                                                                                                                                              1. ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
                                                                                                                                                                                                                                                                                                1. //判断当前的搜索策略是否是PARENTS或者ANCESTORS,默认是ALL
                                                                                                                                                                                                                                                                                                  1. if (beans.getStrategy() == SearchStrategy.PARENTS || beans.getStrategy() == SearchStrategy.ANCESTORS) {
                                                                                                                                                                                                                                                                                                    1. BeanFactory parent = beanFactory.getParentBeanFactory();
                                                                                                                                                                                                                                                                                                      1. Assert.isInstanceOf(ConfigurableListableBeanFactory.class, parent, "Unable to use SearchStrategy.PARENTS");
                                                                                                                                                                                                                                                                                                        1. //如果是PARENTS或者ANCESTORS,当前bean工厂就用父工厂
                                                                                                                                                                                                                                                                                                          1. beanFactory = (ConfigurableListableBeanFactory)parent;
                                                                                                                                                                                                                                                                                                            1. }
                                                                                                                                                                                                                                                                                                                1. if (beanFactory == null) {
                                                                                                                                                                                                                                                                                                                  1. return Collections.emptyList();
                                                                                                                                                                                                                                                                                                                    1. } else {
                                                                                                                                                                                                                                                                                                                      1. List<String> beanNames = new ArrayList();
                                                                                                                                                                                                                                                                                                                        1. //如果当前搜索策略等于CURRENT,为true
                                                                                                                                                                                                                                                                                                                          1. boolean considerHierarchy = beans.getStrategy() != SearchStrategy.CURRENT;
                                                                                                                                                                                                                                                                                                                            1. //这里的type就是需要查找的bean的类型
                                                                                                                                                                                                                                                                                                                              1. //下面,会从属性中找bean
                                                                                                                                                                                                                                                                                                                                1. Iterator var6 = beans.getTypes().iterator();
                                                                                                                                                                                                                                                                                                                                    1. String beanName;
                                                                                                                                                                                                                                                                                                                                      1. while(var6.hasNext()) {
                                                                                                                                                                                                                                                                                                                                        1. beanName = (String)var6.next();
                                                                                                                                                                                                                                                                                                                                          1. //如果找到了类型,接下来就是根据类型找bean的实例名,找示例名的方法在下方,实际上就是一个getNamesForType
                                                                                                                                                                                                                                                                                                                                            1. beanNames.addAll(this.getBeanNamesForType(beanFactory, beanName, context.getClassLoader(), considerHierarchy));
                                                                                                                                                                                                                                                                                                                                              1. }
                                                                                                                                                                                                                                                                                                                                                  1. var6 = beans.getIgnoredTypes().iterator();
                                                                                                                                                                                                                                                                                                                                                      1. while(var6.hasNext()) {
                                                                                                                                                                                                                                                                                                                                                        1. beanName = (String)var6.next();
                                                                                                                                                                                                                                                                                                                                                          1. beanNames.removeAll(this.getBeanNamesForType(beanFactory, beanName, context.getClassLoader(), considerHierarchy));
                                                                                                                                                                                                                                                                                                                                                            1. }
                                                                                                                                                                                                                                                                                                                                                                1. var6 = beans.getAnnotations().iterator();
                                                                                                                                                                                                                                                                                                                                                                    1. while(var6.hasNext()) {
                                                                                                                                                                                                                                                                                                                                                                      1. beanName = (String)var6.next();
                                                                                                                                                                                                                                                                                                                                                                        1. beanNames.addAll(Arrays.asList(this.getBeanNamesForAnnotation(beanFactory, beanName, context.getClassLoader(), considerHierarchy)));
                                                                                                                                                                                                                                                                                                                                                                          1. }
                                                                                                                                                                                                                                                                                                                                                                              1. var6 = beans.getNames().iterator();
                                                                                                                                                                                                                                                                                                                                                                                  1. while(var6.hasNext()) {
                                                                                                                                                                                                                                                                                                                                                                                    1. beanName = (String)var6.next();
                                                                                                                                                                                                                                                                                                                                                                                      1. if (this.containsBean(beanFactory, beanName, considerHierarchy)) {
                                                                                                                                                                                                                                                                                                                                                                                        1. beanNames.add(beanName);
                                                                                                                                                                                                                                                                                                                                                                                          1. }
                                                                                                                                                                                                                                                                                                                                                                                            1. }
                                                                                                                                                                                                                                                                                                                                                                                              1. //将存放bean实例名的list返回
                                                                                                                                                                                                                                                                                                                                                                                                1. return beanNames;
                                                                                                                                                                                                                                                                                                                                                                                                  1. }
                                                                                                                                                                                                                                                                                                                                                                                                    1. }
                                                                                                                                                                                                                                                                                                                                                                                                            1. //根据类型获取bean的name
                                                                                                                                                                                                                                                                                                                                                                                                              1. private Collection<String> getBeanNamesForType(ListableBeanFactory beanFactory, String type, ClassLoader classLoader, boolean considerHierarchy) throws LinkageError {
                                                                                                                                                                                                                                                                                                                                                                                                                1. try {
                                                                                                                                                                                                                                                                                                                                                                                                                  1. Set<String> result = new LinkedHashSet();
                                                                                                                                                                                                                                                                                                                                                                                                                    1. this.collectBeanNamesForType(result, beanFactory, ClassUtils.forName(type, classLoader), considerHierarchy);
                                                                                                                                                                                                                                                                                                                                                                                                                      1. return result;
                                                                                                                                                                                                                                                                                                                                                                                                                        1. } catch (ClassNotFoundException var6) {
                                                                                                                                                                                                                                                                                                                                                                                                                          1. return Collections.emptySet();
                                                                                                                                                                                                                                                                                                                                                                                                                            1. } catch (NoClassDefFoundError var7) {
                                                                                                                                                                                                                                                                                                                                                                                                                              1. return Collections.emptySet();
                                                                                                                                                                                                                                                                                                                                                                                                                                1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                  1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                      1. private void collectBeanNamesForType(Set<String> result, ListableBeanFactory beanFactory, Class<?> type, boolean considerHierarchy) {
                                                                                                                                                                                                                                                                                                                                                                                                                                        1. result.addAll(BeanTypeRegistry.get(beanFactory).getNamesForType(type));
                                                                                                                                                                                                                                                                                                                                                                                                                                          1. if (considerHierarchy && beanFactory instanceof HierarchicalBeanFactory) {
                                                                                                                                                                                                                                                                                                                                                                                                                                            1. BeanFactory parent = ((HierarchicalBeanFactory)beanFactory).getParentBeanFactory();
                                                                                                                                                                                                                                                                                                                                                                                                                                              1. if (parent instanceof ListableBeanFactory) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                1. this.collectBeanNamesForType(result, (ListableBeanFactory)parent, type, considerHierarchy);
                                                                                                                                                                                                                                                                                                                                                                                                                                                  1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                                    1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                                        1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                                      1.  

                                                                                                                                                                                                                                                                                                                                                                                                                                                      找完bean了之后,回到刚才的代码里:

                                                                                                                                                                                                                                                                                                                                                                                                                                                        1. //如果当前注入的bean是@ConditionalOnMissingBean
                                                                                                                                                                                                                                                                                                                                                                                                                                                          1. if (metadata.isAnnotated(ConditionalOnMissingBean.class.getName())) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                            1. //返回一个spec(说明),这里的spec规定了搜索的内容,比如搜索策略、需要搜索的类名......
                                                                                                                                                                                                                                                                                                                                                                                                                                                              1. spec = new OnBeanCondition.BeanSearchSpec(context, metadata, ConditionalOnMissingBean.class);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                1. matching = this.getMatchingBeans(context, spec);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1. if (!matching.isEmpty()) {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1. return ConditionOutcome.noMatch(ConditionMessage.forCondition(ConditionalOnMissingBean.class, new Object[]{spec}).found("bean", "beans").items(Style.QUOTE, matching));
                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1. matchMessage = matchMessage.andCondition(ConditionalOnMissingBean.class, new Object[]{spec}).didNotFind("any beans").atAll();
                                                                                                                                                                                                                                                                                                                                                                                                                                                                            1. }
                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1.  

                                                                                                                                                                                                                                                                                                                                                                                                                                                                          如果第5行返回的list不是空的,就会返回ConditionOutcome对象noMatch方法,表示不匹配。ConditionOutcome类用于存放过滤结果,只有两个变量:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                            1. /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                              1. * 过滤结果类
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1. */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1. public class ConditionOutcome {
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    1. /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      1. * 匹配结果 true or false
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        1. */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          1. private final boolean match;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            1. /**
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              1. * 匹配结果信息
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1. */
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1. private final ConditionMessage message;
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1.  

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                两者区别:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                @ConditionOnBean在判断list的时候,如果list没有值,返回false,否则返回true

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                @ConditionOnMissingBean在判断list的时候,如果list没有值,返回true,否则返回false,其他逻辑都一样

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                例子:

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                • @ConditionalOnBean(javax.sql.DataSource.class)    

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Spring容器或者所有父容器中需要存在至少一个javax.sql.DataSource类的实例

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                SpringBoot @ConditionalOnBean、@ConditionalOnMissingBean注解源码分析与示例的更多相关文章

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1. SpringBoot的条件注解源码解析

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  SpringBoot的条件注解源码解析 @ConditionalOnBean.@ConditionalOnMissingBean 启动项目 会在ConfigurationClassBeanDefini ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                2. Springboot 加载配置文件源码分析

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Springboot 加载配置文件源码分析 本文的分析是基于springboot 2.2.0.RELEASE. 本篇文章的相关源码位置:https://github.com/wbo112/blogde ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                3. Spring笔记(5) - 声明式事务@EnableTransactionManagement注解源码分析

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  一.背景 前面详解了实现Spring事务的两种方式的不同实现:编程式事务和声明式事务,对于配置都使用到了xml配置,今天介绍Spring事务的注解开发,例如下面例子: 配置类:注册数据源.JDBC模板 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                4. java io系列02之 ByteArrayInputStream的简介,源码分析和示例(包括InputStream)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  我们以ByteArrayInputStream,拉开对字节类型的“输入流”的学习序幕.本章,我们会先对ByteArrayInputStream进行介绍,然后深入了解一下它的源码,最后通过示例来掌握它的 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                5. java io系列03之 ByteArrayOutputStream的简介,源码分析和示例(包括OutputStream)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  前面学习ByteArrayInputStream,了解了“输入流”.接下来,我们学习与ByteArrayInputStream相对应的输出流,即ByteArrayOutputStream.本章,我们会 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                6. java io系列04之 管道(PipedOutputStream和PipedInputStream)的简介,源码分析和示例

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  本章,我们对java 管道进行学习. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_04.html java 管道介绍 在java中,PipedOu ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                7. springBoot从入门到源码分析

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  先分享一个springBoot搭建学习项目,和springboot多数据源项目的传送门:https://github.com/1057234721/springBoot 1. SpringBoot快速 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                8. spring注解源码分析--how does autowired works?

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1. 背景 注解可以减少代码的开发量,spring提供了丰富的注解功能.我们可能会被问到,spring的注解到底是什么触发的呢?今天以spring最常使用的一个注解autowired来跟踪代码,进行d ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                9. SpringBoot拦截器及源码分析

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  1.拦截器是什么 java里的拦截器(Interceptor)是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                随机推荐

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                1. 编写第一Spring程序

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  构建Spring项目 通过https://start.spring.io/来构建项目,在这里我选择了两个依赖,web 和 Actuator. 项目结构 通过eclipse导入项目,可以看到这是一个标准 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                2. 51nod2006 飞行员配对(二分图最大匹配)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  2006 飞行员配对(二分图最大匹配) 题目来源: 网络流24题 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 第二次世界大战时期,英国皇家空军从沦陷国 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                3. pyDes 实现 Python 版的 DES 对称加密/解密--转

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  https://my.oschina.net/leejun2005/blog/586451 手头有个 Java 版的 DES 加密/解密程序,最近想着将其 Python 重构下,方便后续脚本解析,捣鼓 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                4. Shell脚本,简单& 强大

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    摘自<码农增刊Linus与Linux>,章节:你可能不知道的Shell.   最近阅读完这本书,觉得其中有很多不错的内容,这是其中的一个Shell小甜点,拿来和大家一起分享一下,增加了 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                5. 关于mybatis的xml文件中使用 >= 或者 <= 号报错的解决方案

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  当我们需要通过xml格式处理sql语句时,经常会用到< ,<=,>,>=等符号,但是很容易引起xml格式的错误,这样会导致后台将xml字符串转换为xml文档时报错,从而导致程序 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                6. SqlServer知识点-操作xml

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  一.开发环境 SQL2010 二.开发过程 1.声明一个xml类型变量 DECLARE @xmlInfo XML; SET @xmlInfo = '<CompanyGroup> <C ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                7. Pro ASP.NET Core MVC 6th 第三章

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  第三章 MVC 模式,项目和约定 在深入了解ASP.NET Core MVC的细节之前,我想确保您熟悉MVC设计模式背后的思路以及将其转换为ASP.NET Core MVC项目的方式. 您可能已经了解 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                8. java多线程之内存的可见性介绍(备用1)

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  (仅供参考) a.共享变量的可见能够一定程度保证线程安全,共享变量不可见导致数据不够准确,出现各种各样的问题,导致线程不安全. b.不同线程之间无法直接访问其他线程工作内存中的变量. 1.可见性 2. ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                9. golang 自定义time.Time json输出格式

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  工作中使用golang时,遇到了一个问题.声明的struct含time.Time类型.使用json格式化struct时,time.Time被格式化成”2006-01-02T15:04:05.99999 ...

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                10. Swift mutating Equatable Hashable 待研究

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  Swift mutating Equatable Hashable 待研究