Pārlūkot izejas kodu

0125 springboot自动配置原理

Qing 1 gadu atpakaļ
vecāks
revīzija
ae451e79d1
28 mainītis faili ar 383 papildinājumiem un 6 dzēšanām
  1. 16 1
      springboot-demo/src/main/java/com/sf/DemoApplication.java
  2. 12 0
      springboot-demo/src/main/java/com/sf/bean/Computer.java
  3. 12 0
      springboot-demo/src/main/java/com/sf/bean/Phone.java
  4. 33 0
      springboot-demo/src/main/java/com/sf/config/BeanConfig.java
  5. 57 0
      springboot-demo/src/main/java/com/sf/config/MyAutoConfig.java
  6. 1 1
      springboot-demo/src/main/java/com/sf/config/VegetablesConfig.java
  7. 11 0
      springboot-demo/src/main/java/com/sf/config/other/OtherAutoConfig1.java
  8. 11 0
      springboot-demo/src/main/java/com/sf/config/other/OtherAutoConfig2.java
  9. 5 0
      springboot-demo/src/main/java/com/sf/lambda/Command.java
  10. 5 0
      springboot-demo/src/main/java/com/sf/lambda/CommandCompare.java
  11. 5 0
      springboot-demo/src/main/java/com/sf/lambda/CommandMethod.java
  12. 5 0
      springboot-demo/src/main/java/com/sf/lambda/CommandOneParam.java
  13. 5 0
      springboot-demo/src/main/java/com/sf/lambda/CommandSimple.java
  14. 120 0
      springboot-demo/src/main/java/com/sf/lambda/CommandTest.java
  15. 9 0
      springboot-demo/src/main/java/com/sf/lambda/LengthComparator.java
  16. 10 0
      springboot-demo/src/main/java/com/sf/lambda/ProcessArray.java
  17. 14 0
      springboot-demo/src/main/java/com/sf/lambda/impl/AddCommand.java
  18. 12 0
      springboot-demo/src/main/java/com/sf/lambda/impl/PrintCommand.java
  19. 4 0
      springboot-demo/src/main/resources/META-INF/spring.factories
  20. 0 1
      springboot-demo/src/main/resources/application-dev.properties
  21. 0 1
      springboot-demo/src/main/resources/application-prod.properties
  22. 0 1
      springboot-demo/src/main/resources/application-test.properties
  23. 1 0
      springboot-demo/src/main/resources/config/application-dev.properties
  24. 1 0
      springboot-demo/src/main/resources/config/application-prod.properties
  25. 1 0
      springboot-demo/src/main/resources/config/application-test.properties
  26. 0 0
      springboot-demo/src/main/resources/config/vegetables.properties
  27. 1 1
      springboot-demo/src/test/java/com/sf/ApplicationTests.java
  28. 32 0
      springboot-demo/src/test/java/com/sf/BeanTests.java

+ 16 - 1
springboot-demo/src/main/java/com/sf/DemoApplication.java

@@ -1,5 +1,6 @@
 package com.sf;
 
+import com.sf.bean.Computer;
 import com.sf.config.FoodConfig;
 import com.sf.config.VegetablesConfig;
 import org.mybatis.spring.annotation.MapperScan;
@@ -9,8 +10,12 @@ import org.springframework.boot.CommandLineRunner;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.ComponentScan;
 
+import java.util.Arrays;
+
 // @SpringBootApplication是springboot提供的注解
 // 标志一个类是 springboot的应用程序的主函数入口
 // 默认扫描路径是当前类所在的路径  以及子路径  当前项目中的“com.sf”
@@ -29,7 +34,17 @@ public class DemoApplication implements CommandLineRunner {
         //   Hello.java ->  javac Hello.java  ->   Hello.class
         //   java Hello 1 2    args={1,2}
         //   接收启动时传进来的参数  spring也支持一些指定参数的传递
-        SpringApplication.run(DemoApplication.class, args);
+        ConfigurableApplicationContext context = SpringApplication.run(DemoApplication.class, args);
+        String[] names = context.getBeanDefinitionNames();
+//        System.out.println(Arrays.toString(names));
+        // 先获取数组对应的stream(数据流)  然后使用foreach进行遍历 遍历过程中进行打印
+        Arrays.stream(names).forEach(System.out::println);
+    }
+
+    // @SpringBootConfiguration -> @Configuration
+    @Bean
+    public Computer computer11(){
+        return new Computer("from DemoApplication");
     }
 
     @Override

+ 12 - 0
springboot-demo/src/main/java/com/sf/bean/Computer.java

@@ -0,0 +1,12 @@
+package com.sf.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Computer {
+    private String name;
+}

+ 12 - 0
springboot-demo/src/main/java/com/sf/bean/Phone.java

@@ -0,0 +1,12 @@
+package com.sf.bean;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class Phone {
+    private String name;
+}

+ 33 - 0
springboot-demo/src/main/java/com/sf/config/BeanConfig.java

@@ -0,0 +1,33 @@
+package com.sf.config;
+
+import com.sf.bean.Computer;
+import com.sf.bean.Phone;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class BeanConfig {
+
+//    @Bean("computer")
+    public Computer computer() {
+        return new Computer("笔记本");
+    }
+
+    // @ConditionalOnMissingBean 是在不存在某个bean的情况下才会往后执行
+    // @ConditionalOnBean 是在存在某个bean的情况下才会往后执行
+//    @ConditionalOnMissingBean(Computer.class)
+//    @Bean("computer")
+    public Computer computerOther() {
+        return new Computer("备用");
+    }
+
+    @ConditionalOnBean(Computer.class)
+    @Bean
+    public Phone phone() {
+        return new Phone("小米");
+    }
+
+
+}

+ 57 - 0
springboot-demo/src/main/java/com/sf/config/MyAutoConfig.java

@@ -0,0 +1,57 @@
+package com.sf.config;
+
+import com.sf.bean.Computer;
+import com.sf.config.other.OtherAutoConfig1;
+import com.sf.config.other.OtherAutoConfig2;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Import;
+import org.springframework.context.annotation.ImportSelector;
+import org.springframework.core.io.support.SpringFactoriesLoader;
+import org.springframework.core.type.AnnotationMetadata;
+
+import java.util.List;
+
+@Configuration
+//@Import({OtherAutoConfig1.class})
+//@Import({OtherAutoConfig1.class, OtherAutoConfig2.class})
+@Import(MyAutoConfig.MyImportSelector.class)
+public class MyAutoConfig {
+
+    @Bean("computer")
+    public Computer computer() {
+        return new Computer("我的笔记本");
+    }
+
+    // @Configuration -> @Import({})  -> ImportSelector选择器
+    static class MyImportSelector implements ImportSelector {
+        @Override
+        public String[] selectImports(AnnotationMetadata importingClassMetadata) {
+            // 加载我们编写的spring.factories文件
+            // com.sf.config.MyAutoConfig$MyImportSelector=\
+            //  com.sf.config.MyAutoConfig.OtherAutoConfig1,\
+            //  com.sf.config.MyAutoConfig.OtherAutoConfig2
+            List<String> factoryNames = SpringFactoriesLoader.
+                    loadFactoryNames(MyImportSelector.class, null);
+            return factoryNames.toArray(new String[0]);
+        }
+    }
+
+    // 静态内部类
+    // 被调用时  外部类.静态内部类.class
+//    @Configuration
+//    static class OtherAutoConfig1 {
+//        @Bean("oneComputer")
+//        public Computer computer() {
+//            return new Computer("one的笔记本");
+//        }
+//    }
+//
+////    @Configuration
+//    static class OtherAutoConfig2 {
+//        @Bean("twoComputer")
+//        public Computer computer() {
+//            return new Computer("two的笔记本");
+//        }
+//    }
+}

+ 1 - 1
springboot-demo/src/main/java/com/sf/config/VegetablesConfig.java

@@ -8,7 +8,7 @@ import org.springframework.context.annotation.PropertySource;
 @Data
 @Configuration
 @ConfigurationProperties(prefix = "vegetables")
-@PropertySource("classpath:vegetables.properties")
+@PropertySource("classpath:config/vegetables.properties")
 public class VegetablesConfig {
     private String potato;
     private String eggplant;

+ 11 - 0
springboot-demo/src/main/java/com/sf/config/other/OtherAutoConfig1.java

@@ -0,0 +1,11 @@
+package com.sf.config.other;
+
+import com.sf.bean.Computer;
+import org.springframework.context.annotation.Bean;
+
+public class OtherAutoConfig1 {
+    @Bean("oneComputer")
+    public Computer computer() {
+        return new Computer("one的笔记本");
+    }
+}

+ 11 - 0
springboot-demo/src/main/java/com/sf/config/other/OtherAutoConfig2.java

@@ -0,0 +1,11 @@
+package com.sf.config.other;
+
+import com.sf.bean.Computer;
+import org.springframework.context.annotation.Bean;
+
+public class OtherAutoConfig2 {
+    @Bean("twoComputer")
+    public Computer computer() {
+        return new Computer("two的笔记本");
+    }
+}

+ 5 - 0
springboot-demo/src/main/java/com/sf/lambda/Command.java

@@ -0,0 +1,5 @@
+package com.sf.lambda;
+
+public interface Command {
+    void process(int[] target);
+}

+ 5 - 0
springboot-demo/src/main/java/com/sf/lambda/CommandCompare.java

@@ -0,0 +1,5 @@
+package com.sf.lambda;
+
+public interface CommandCompare {
+    int compare(String first, String second);
+}

+ 5 - 0
springboot-demo/src/main/java/com/sf/lambda/CommandMethod.java

@@ -0,0 +1,5 @@
+package com.sf.lambda;
+
+public interface CommandMethod {
+    int compare(int x, int y);
+}

+ 5 - 0
springboot-demo/src/main/java/com/sf/lambda/CommandOneParam.java

@@ -0,0 +1,5 @@
+package com.sf.lambda;
+
+public interface CommandOneParam {
+    void process(int x);
+}

+ 5 - 0
springboot-demo/src/main/java/com/sf/lambda/CommandSimple.java

@@ -0,0 +1,5 @@
+package com.sf.lambda;
+
+public interface CommandSimple {
+    void process();
+}

+ 120 - 0
springboot-demo/src/main/java/com/sf/lambda/CommandTest.java

@@ -0,0 +1,120 @@
+package com.sf.lambda;
+
+import com.sf.lambda.impl.AddCommand;
+
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.function.Function;
+
+public class CommandTest {
+
+    // 命令模式
+    public static void main(String[] args) {
+        ProcessArray pa = new ProcessArray();
+        int[] arr = {8, 9, 2, 1};
+//        pa.process(target,new PrintCommand());
+//        pa.process(target,new AddCommand());
+
+        // 匿名内部类的使用  是因为不需要关心类的名字  只需要实现接口的处理逻辑
+//        pa.process(arr, new Command() {
+//            @Override
+//            public void process(int[] target) {
+//                System.out.println(Arrays.toString(target));
+//            }
+//        });
+        // lambda表达式  也不再关心方法的名字了  只保留方法的入参和方法的执行逻辑
+        pa.process(arr, (int[] target) -> {
+            System.out.println(Arrays.toString(target));
+        });
+
+        System.out.println("============");
+        // 无参数 无返回值
+        CommandSimple cs = new CommandSimple() {
+            @Override
+            public void process() {
+                System.out.println("CommandSimple");
+            }
+        };
+        cs.process();
+
+        CommandSimple cs1 = () -> {
+            System.out.println("CommandSimple from lambda");
+        };
+        cs1.process();
+
+        CommandSimple cs2 = () -> System.out.println("CommandSimple from lambda Simple");
+        cs2.process();
+
+        System.out.println("============");
+        // 一个参数 无返回值
+        CommandOneParam cop = new CommandOneParam() {
+            @Override
+            public void process(int x) {
+                System.out.println("x=" + x);
+            }
+        };
+        CommandOneParam cop1 = (int x) -> {
+            System.out.println("x=" + x);
+        };
+        cop1.process(10);
+
+        CommandOneParam cop2 = (int x) -> System.out.println("x=" + x);
+        // 能够推断出类型的参数  连类型都可以简化
+        CommandOneParam cop3 = x -> System.out.println(x);
+        cop3.process(20);
+
+        // 是一种进一步对参数的简化  是谁调用了(::)什么方法
+        CommandOneParam cop4 = System.out::println;
+        cop4.process(100);
+
+        // 比较的逻辑 如果第一个长度小 返回-1  如果第一个长度大 返回1  否则返回0
+        CommandCompare cc = new CommandCompare() {
+            @Override
+            public int compare(String first, String second) {
+                return 0;
+            }
+        };
+
+        System.out.println("============");
+        CommandCompare cc1 = (String first, String second) -> {
+            System.out.println("CommandCompare lambda");
+            if (first.length() < second.length()) return -1;
+            if (first.length() > second.length()) return 1;
+            return 0;
+        };
+        System.out.println(cc1.compare("aaa", "bbbb"));
+        CommandCompare cc2 = (first, second) -> {
+            return Integer.compare(first.length(),second.length());
+        };
+
+        CommandCompare cc3 =
+                (first, second) -> Integer.compare(first.length(),second.length());
+        System.out.println(cc3.compare("ccc", "ddd"));
+
+
+        System.out.println("============");
+        CommandMethod cm = Math::max;
+        CommandMethod cm1 = Math::min;
+        CommandMethod cm2 = (int x,int y) -> { return Math.max(x,y);};
+        CommandMethod cm3 = ( x, y) -> Math.max(x,y);
+
+        System.out.println("============");
+        // 调用
+        System.out.println(subStr("我Code,我快乐", str -> str.substring(0, 5)));
+        // 匿名内部类
+        subStr("数据", new Function<String, String>() {
+            @Override
+            public String apply(String s) {
+                return "处理逻辑";
+            }
+        });
+        subStr("数据",(String s)->{return "处理逻辑";});
+        subStr("数据", s-> "处理逻辑");
+    }
+
+    // 声明方法   y=f(x)  R=f(T)   String=f(String)
+    public static String subStr(String str, Function<String, String> function){
+        return function.apply(str);
+    }
+
+}

+ 9 - 0
springboot-demo/src/main/java/com/sf/lambda/LengthComparator.java

@@ -0,0 +1,9 @@
+package com.sf.lambda;
+
+import java.util.Comparator;
+
+class LengthComparator implements Comparator<String> {
+    public int compare(String first, String second) {
+        return Integer.compare(first.length(), second.length());
+    }
+}

+ 10 - 0
springboot-demo/src/main/java/com/sf/lambda/ProcessArray.java

@@ -0,0 +1,10 @@
+package com.sf.lambda;
+
+public class ProcessArray {
+
+    // Command是一种指令或命令  用来去处理数组的  是接口 处理的逻辑是不确定的
+    // ProcessArray是一种处理数组的操作类  需要两个参数  数组本身 操作的行为
+    public void process(int[] target,Command command){
+        command.process(target);
+    }
+}

+ 14 - 0
springboot-demo/src/main/java/com/sf/lambda/impl/AddCommand.java

@@ -0,0 +1,14 @@
+package com.sf.lambda.impl;
+
+import com.sf.lambda.Command;
+
+public class AddCommand implements Command {
+    @Override
+    public void process(int[] target) {
+        int sum = 0;
+        for (int i = 0; i < target.length; i++) {
+            sum += target[i];
+        }
+        System.out.println("加和:" + sum);
+    }
+}

+ 12 - 0
springboot-demo/src/main/java/com/sf/lambda/impl/PrintCommand.java

@@ -0,0 +1,12 @@
+package com.sf.lambda.impl;
+
+import com.sf.lambda.Command;
+
+public class PrintCommand implements Command {
+    @Override
+    public void process(int[] target) {
+        for (int i = 0; i < target.length; i++) {
+            System.out.println(target[i]);
+        }
+    }
+}

+ 4 - 0
springboot-demo/src/main/resources/META-INF/spring.factories

@@ -0,0 +1,4 @@
+com.sf.config.MyAutoConfig$MyImportSelector=\
+  com.sf.config.other.OtherAutoConfig1
+#  com.sf.config.other.OtherAutoConfig1,\
+#  com.sf.config.other.OtherAutoConfig2

+ 0 - 1
springboot-demo/src/main/resources/application-dev.properties

@@ -1 +0,0 @@
-server.port=19090

+ 0 - 1
springboot-demo/src/main/resources/application-prod.properties

@@ -1 +0,0 @@
-server.port=11010

+ 0 - 1
springboot-demo/src/main/resources/application-test.properties

@@ -1 +0,0 @@
-server.port=12020

+ 1 - 0
springboot-demo/src/main/resources/config/application-dev.properties

@@ -0,0 +1 @@
+#server.port=19090

+ 1 - 0
springboot-demo/src/main/resources/config/application-prod.properties

@@ -0,0 +1 @@
+#server.port=11010

+ 1 - 0
springboot-demo/src/main/resources/config/application-test.properties

@@ -0,0 +1 @@
+#server.port=12020

+ 0 - 0
springboot-demo/src/main/resources/vegetables.properties → springboot-demo/src/main/resources/config/vegetables.properties


+ 1 - 1
springboot-demo/src/test/java/com/sf/DemoApplicationTests.java → springboot-demo/src/test/java/com/sf/ApplicationTests.java

@@ -7,7 +7,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 
 @SpringBootTest
-class DemoApplicationTests {
+class ApplicationTests {
 
     @Autowired
     private HelloController helloController;

+ 32 - 0
springboot-demo/src/test/java/com/sf/BeanTests.java

@@ -0,0 +1,32 @@
+package com.sf;
+
+import com.sf.bean.Computer;
+import com.sf.bean.Phone;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+
+import java.util.Map;
+
+@SpringBootTest
+public class BeanTests {
+
+//    @Autowired
+//    public Computer computer;
+
+    @Autowired
+    public ApplicationContext applicationContext;
+
+    @Test
+    public void test(){
+//        System.out.println(computer.getName());
+//        Computer bean = (Computer) applicationContext.getBean("computer");
+//        System.out.println(bean.getName());
+        Map<String, Computer> beans = applicationContext.getBeansOfType(Computer.class);
+        System.out.println(beans);
+
+        Map<String, Phone> beanPhones = applicationContext.getBeansOfType(Phone.class);
+        System.out.println(beanPhones);
+    }
+}