1.sprng 簡介

来源:https://www.cnblogs.com/wmd-l/archive/2022/05/05/16226683.html
-Advertisement-
Play Games

分享一下 Idea 的 scope 功能 事情的起因是我在使用 idea 的call hierarchy功能時,覺得它沒有像find usage那樣有排除功能,並且如果點擊了展開全部,當代碼中使用了某些框架導致調用層級非常深時,idea 會占用非常高的 CPU。 於是我去 jetbrains 的缺陷 ...


容器(可以用來管理所有的組件(類))

核心關註:IOC和AOP

1.IOC

Inversion(反轉) Of Control:控制反轉
    控制:資源的獲取方式
        1.主動式(要什麼資源自己創建)
            Person{
                Book book=new Book();
                Dog dog=new Dog();
                //複雜對象的創建時比較龐大的工程
            }
        2.被動式:資源的獲取不是自己創建,而是交給一個容器創建和設置
            Person{
                Book book;
                public void test(){
                    book.read();
                }
            }
    容器:管理所有的組件(有功能的類),主動的new資源改為被動的接受資源

 1.1 DI(Dependency Injection)依賴註入

容器能知道哪個組件(類)運行的時候,需要另外一個組件(類);
容器通過反射的形式,將容器中準備好的Book對象註入(利用反射給屬性賦值)到Person中
IOC只是思想,而DI是具體的實現
代碼實現:
    1.實體類
    public class Person {
        private String name;
        private Integer age;
        private String gender;
        private String email;
        public Person() {
            System.out.println("person的構造器!");
        }
        public void setName(String name) {
            System.out.println("設置pserson的name");
            this.name = name;
        }
        public void setAge(Integer age) {
            System.out.println("設置person的age");
            this.age = age;
        }
        public void setGender(String gender) {
            System.out.println("設置person的gender");
            this.gender = gender;
        }
        public void setEmail(String email) {
            System.out.println("設置person的email");
            this.email = email;
        }
      ....
      ...get()
    }
    2.spring的配置文件ioc.xml
        <?xml version="1.0" encoding="UTF-8"?>
        <beans xmlns="http://www.springframework.org/schema/beans"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
            <!--註冊person對象,spring會自動創建這個person對象-->
            <bean class="com.Person" id="person01">
                <property name="age" value="18"></property>------------->name是bean中的屬性,通過set方法反射註入
                <property name="email" value="[email protected]"/>
                <property name="gender" value="男"/>
                <property name="name" value="吳孟達"/>
            </bean>
        </beans>
    3.測試類:
        public class Test {
            public static void main(String[] args) {
                System.out.println("啟動spring容器....");
                ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");--------->啟動spring的配置文件
                System.out.println("spring容器啟動成功!");
                Person person= (Person) ioc.getBean("person01");----------->此處的person01為spring配置文件中的bean的id
                System.out.println(person);
            }
        }
    輸出:
        啟動spring容器....
        person的構造器!
        設置person的age
        設置person的email
        設置person的gender
        設置pserson的name
        spring容器啟動成功!
        Person{name='吳孟達', age=18, gender='男', email='[email protected]'}

結論:------>發現其執行順序為:
    1.<bean...>元素驅動spring容器調用構造器創建對象
    2.<property...>元素驅動spring執行setter方法
如果一個實體類中引用了其他實體類,容器載入的執行順序
1.第一種情況:範圍大的(person引用book)在範圍小的前面
    spring配置文件內容:
        <bean id="person01" class="entity.Person">
            <property name="age" value="18"></property>
            <property name="name" value="吳孟達"></property>
            <property name="book" ref="book"/>
        </bean>
        <bean id="book" class="entity.Book">
            <property name="name" value="java分析"/>
            <property name="price" value="32"/>
        </bean>
    實體類信息:
    。。。
    測試類信息:
        public static void main(String[] args) {
            System.out.println("載入spring....");
            ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
            System.out.println("spring容器啟動成功!");
            Person person= (Person) ac.getBean("person01");
            System.out.println(person.toString());
        }
    輸出:
        載入spring....
        person實例化!
        Book實例化!
        Book執行set name方法
        Book執行set price方法
        person執行set age方法
        person執行set name方法
        spring容器啟動成功!
    發現執行順序為:
        1.先實例化兩個對象
        2.在執行小的set方法
        3.再執行大的set方法


第二種情況:小範圍的在上
    spring配置文件內容:
      <bean id="book" class="entity.Book">
        <property name="name" value="java分析"/>
        <property name="price" value="32"/>
    </bean>
    <bean id="person01" class="entity.Person">
        <property name="age" value="18"></property>
        <property name="name" value="吳孟達"></property>
        <property name="book" ref="book"/>
    </bean>
      輸出:
        Book實例化!
        Book執行set name方法
        Book執行set price方法
        person實例化!
        person執行set age方法
        person執行set name方法
        spring容器啟動成功! 
    執行順序為:
        1.小範圍對象實例化
        2.小範圍對象set方法
        3.大範圍對象實例化
        4.大範圍對象set方法

 

2.源碼解析

1.
 以此為示例:
     <bean id="book" class="entity.Book"></bean>
    實際上<bean.../>元素預設一反射的方式來調用該類的無參構造器
    底層簡單源碼如下:
        String idStr=...;//解析<bean。。。。/>元素的id屬性得到該欄位的字元串值為"book"
        String classStr=...;//解析class屬性得到該欄位的值為:entity.Book
        Class clazz=Class.forName(classStr);
        Object object=clazz.newInstance();//通過反射示例化對象
        container.put(idstr,obj);//將對象放入容器給中,container為spring容器
    
2.
   <bean id="person01" class="entity.Person">
        <property name="book" ref="book"/>
    </bean>
    底層的簡單源碼如下:
        String nameStr=...;解析<property.../>元素的name屬性得到該字元串的值為book
        String refStr=..;解析<property.../>元素的ref屬性得到該字元串的值為book
        String setterName-"set"+nameStr.subString(0,1).toUpperCase()+name.subString(1);//生成將要調用的setter方法】
        Object paramBean=container.get(refStr);//從容器中取到refStr的bean,作為傳入參數
        Method setter=clazz.getMethod(setterName,parmBean.getClass())//此處的clazz和1的對應起來
        setter.incoke(obj,parmBean);//此處的obj和1的對應起來

 

3.組件在spring容器中是單例的

public static void main(String[] args) {
        System.out.println("載入spring....");
        ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
        System.out.println("spring容器啟動成功!");
        Person person1= (Person) ac.getBean("person01");
        Person person2= (Person) ac.getBean("person01");
        System.out.println(person1==person2);------------------------->此時輸出為true;
}

 

4.使用構造器為bean的屬性賦值

spring配置文件為:
    <bean id="book" class="entity.Book">
        <property name="name" value="java分析"/>
        <property name="price" value="32"/>
    </bean>
    <bean id="person01" class="entity.Person">-------------------------------->此處有兩個person的bean:這一個使用set方法給屬性賦值,調用的是無參構造器
        <property name="age" value="18"></property>
        <property name="name" value="吳孟達"></property>
        <property name="book" ref="book"/>
    </bean>
    <bean id="person02" class="entity.Person">------------------------------>這裡調用的是有參構造器來進行屬性賦值
        <constructor-arg name="age" value="18"></constructor-arg>
        <constructor-arg name="book" ref="book"></constructor-arg>
        <constructor-arg name="name" value="吳孟達02"></constructor-arg>
    </bean>
person類的代碼:
    public class Person {
        private String name;
        private Integer age;
        private Book book;
        public Person() {
            System.out.println("person執行無參構造器");
        }
        public Person(String name, Integer age, Book book) {
            this.name = name;
            this.age = age;
            this.book = book;
            System.out.println("person執行有參構造器");
        }
        get/set方法
    }
測試類方法:
    public static void main(String[] args) {
        System.out.println("載入spring....");
        ApplicationContext ac=new ClassPathXmlApplicationContext("ioc.xml");
        System.out.println("spring容器啟動成功!");
        Person person= (Person) ac.getBean("person02");
        System.out.println(person.toString());
    }
輸出:
    載入spring...
    Book實例化!
    Book執行set name方法
    Book執行set price方法 
    person執行無參構造器-------------->調用無參構造器實例化對象,然後調用set方法賦值
    person執行set age方法
    person執行set name方法
    person執行有參構造器-------------->調用有參構造器,並且直接賦值
    spring容器啟動成功!
    Person{name='吳孟達02', age=18, book=Book{name='java分析', price=32}}

 

5.使用p名稱空間為bean屬性賦值

1.在spring的xml文件中加入這一句:xmlns:p="http://www.springframework.org/schema/p"
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:p="http://www.springframework.org/schema/p"----------------------------------->加入這一句
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
        <bean id="book" class="entity.Book">
            <property name="name" value="java分析"/>
            <property name="price" value="32"/>
        </bean>
        <bean id="person03" class="entity.Person" p:age="18" p:name="吳孟達03" p:book-ref="book"></bean>------>此時可以通過p標簽進行賦值
    </beans>

 

 

6.複雜賦值

1.給屬性賦值null
    <bean id="person04" class="entity.Person">
        <property name="name">
            <null></null>---------------------------->使用null標簽進行賦值:不能使用<property name="name" value="null">這是付了一個null的字元串
        </property>
    </bean>
    
2.屬性是引用時
    2.1引用外部bean
        <bean id="book" class="entity.Book">
            <property name="name" value="java分析"/>
            <property name="price" value="32"/>
        </bean>
        <bean id="person04" class="entity.Person">
            <property name="name">
                <null></null>
            </property>
            <property name="book" ref="book"></property>------------->如果外邊已經有了像引用的Book bean,則使用ref引用:這裡意思是:book=ioc.getBean("book")
        </bean>
        測試代碼:
            ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
            Person person= (Person) ioc.getBean("person04");
            System.out.println(ioc.getBean("book")==person.getBook());------------->此時輸出為true
    2.2內部引用
        <bean id="person04" class="entity.Person">
            <property name="name">
                <null></null>
            </property>
            <property name="book">
                <!--對象我們可以使用bean標簽創建 book=new Book();引用內部bean-->
                <bean class="entity.Book">---------------------------------------->此處需要註意的是:內部bean不能直接通過ioc容器獲取:
                    <property name="name" value="java"></property>           ----->如<bean id="bookInner" class="entity.Book">內部bean加上id
                    <property name="price" value="25"></property>            ------>ioc.getBean("bookInner")會獲取出錯!
                </bean>
            </property>
        </bean>
        測試代碼為:
             ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
            Person person= (Person) ioc.getBean("person04");
            System.out.println(ioc.getBean("book")==person.getBook());------------->此時輸出為false

3.為list屬性賦值
    為psrson新增屬性
        private List<Book> library;
    如何為library賦值
        <property name="library">
            <!--library=new ArrayLiast<Book>-->
            <list>-------------------------------->使用過list標簽
                <bean class="entity.Book" p:name="java" p:price="14"></bean>------>1.用bean標簽創建list元素
                <ref bean="book"></ref>-------------------------------------------->2.用ref標簽引入外部bean
            </list>
        </property>
        
4.為map賦值
    為person新增一個屬性
        private Map map;
    springxml中的配置
      <property name="map">
            <map>-------------------------------------------->使用map標簽:map=new HashMap<>();
                <entry key="key01" value="張三"></entry>
                <entry key="key02" value="18"></entry>
                <entry key="book01" value-ref="book"></entry>----->可以使用value-ref引入外部bean
                <entry key="key04">
                    <bean class="entity.Person" p:name="吳孟達" p:age="18" p:book-ref="book"></bean>------>也可以使用該方式引入內部bean
                </entry>
                <entry key="key05">---->map中嵌套map
                    <map>
        
                    </map>
                </entry>
            </map>
        </property>  

5.為Properties賦值
    person新增一個屬性:
        private Properties properties;
    spring的配置文件中:
        <property name="properties">
            <!--properties=new Properties();所有的k=v都是String-->
            <props>
                <!--k=v都是string,值直接寫在標簽中-->
                <prop key="username">root</prop>
                <prop key="password">123456</prop>
            </props>
        </property>
        
6.使用util名稱空間創建集合類型的bean
    使用場景:如果相同的map或者list在多處都有引用
    可以將map或list單獨拿出來做個bean
    使用步驟
        1.在spring的配置文件中加入:xmlns:util="http://www.springframework.org/schema/util"
            <?xml version="1.0" encoding="UTF-8"?>
            <beans xmlns="http://www.springframework.org/schema/beans"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                   xmlns:p="http://www.springframework.org/schema/p"
                   xmlns:util="http://www.springframework.org/schema/util"---------------------->在spring的配置文件中加入這行
                   xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
                   。。。。。
               </bean>
       2.
           <!--相當於new LinkedHashMap<>()-->
            <util:map id="mymap">
                <!--往map中添加元素-->
                <entry key="key01" value="張三"></entry>
                <entry key="key02" value="18"></entry>
                <entry key="book01" value-ref="book"></entry>
                <entry key="key04">
                    <bean class="entity.Person" p:name="吳孟達" p:age="18" p:book-ref="book"></bean>
                </entry>
                <entry key="key05">
                    <map></map>
                </entry>
            </util:map>
        3.其他地方的使用
            <property name="map" ref="mymap"></property>----->直接根據引用獲取即可
            也可以在代碼中直接獲取
            Map<String,Object> map= (Map<String, Object>) ioc.getBean("mymap");

7.util:list的使用和list標簽類似
    <util:list id="mylist">
        <bean class="entity.Person" p:book="西游" p:name="吳孟達"></bean>
        <ref bean="mymap"></ref>
        <value>12</value>
    </util:list>

8.級聯屬性:屬性的屬性
    <bean id="book" class="entity.Book">
        <property name="name" value="java分析"/>
        <property name="price" value="32"/>
    </bean>
    <bean id="person05" class="entity.Person">
        <property name="book" ref="book"></property>
        <property name="book.price" value="1000"></property>
        ----->這裡通過book.price直接更改:person的book屬性的price屬性:但這裡註意的是這裡一改,容器中的book的bean的price屬性改為1000
    </bean>

9.通過繼承實現bean屬性的重用
    <bean id="person01" class="entity.Person">
        <property name="age" value="18"></property>
        <property name="name" value="吳孟達"></property>
        <property name="book" ref="book"/>
    </bean>
    這裡需要一個personbean,其他屬性都一樣,只有age屬性變為19,則可以這樣
    <bean id="person06" class="entity.Person" parent="person01">--------->使用parent屬性,指定需要繼承屬性的bean id,這裡的繼承只是當前bean的配置信息繼承,並不是真正的類繼承
        <property name="name" value="劉丹"></property>
    </bean>
    結論:
       1. 這裡的person01和pserson06在容器中是不同的組件(對象)
       2.這兩個組件的屬性都相同,只有name屬性值不同
       3.因為指定了要繼承配置信息的類,所以上述還可以這樣寫
            <bean id="person06" parent="person01">-------------------------->省略了class,因為配置信息繼承於person01,所以class配置值可以繼承person01的class配置值值
                     <property name="name" value="劉丹"></property>
            </bean>
        4.父類的信息不會因為子類而更改!
10.專門建立一個供其他bean繼承的bean
     <bean id="person01" class="entity.Person" abstract="true">----------------------->加入:abstract="true"
        <property name="age" value="18"></property>
        <property name="name" value="吳孟達"></property>
        <property name="book" ref="book"/>
    </bean>
    abstract="true"這個bean的配置是一個抽象的,不能獲取他的實例,只能被別人繼承
    此時:
        ioc.getBean("person01");-------------------->此時獲取會報錯,因為這個是被其他bean繼承的

 

 

7.bean的作用域

1.單例:scope="singleton"
    <bean id="person05" class="entity.Person" scope="singleton">
        <property name="book" ref="book"></property>
        <property name="book.price" value="1000"></property>
    </bean>
2.多例:scope="prototype"
    <bean id="person05" class="entity.Person" scope="prototype">
        <property name="book" ref="book"></property>
        <property name="book.price" value="1000"></property>
    </bean>
結論:
    1.scope="singleton"單例模式:預設
        1.1在容器啟動完成前就已經創建好對象,保存在容器中
        1.2任何獲取都是獲取之前創建好的對象
    2.scope="prototype"多例模式
        2.1容器啟動預設不會創建多例的bean
        2.2每次獲取的時候創建這個bean(ioc.getBean("person05"))
        2.3每次獲取都會創建一個新的對象

 

8.bean的生命周期(自定義初始化方法和銷毀方法)

1.當是單例模式
    1.person實體類
        public class Person {
            //person的無參構造器
            public Person() {
                System.out.println("person的無參構造器方法...");
            }
            //自定義初始化方法
            public void initMethod(){
                System.out.println("person的初始化方法");
            }
            //自定義對象銷毀方法
            public void destroyMethod(){
                System.out.println("person的銷毀方法");
            }
        }
    2.spring的配置文件
        <bean id="person" class="entity.Person"
          init-method="initMethod"--------------------------->指定自定義的初始化方法
          destroy-method="destroyMethod"--------------------->指定自定義的銷毀方法
        >
        </bean>
    3.測試類
        public static void main(String[] args) {
            System.out.println("spring容器啟動...");
            ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
            System.out.println("spring容器啟動成功!");
            System.out.println("關閉spring容器...");
            ioc.close();---------------------------------------->調用容器的停止方法
            System.out.println("關閉spring容器成功!");
        }
    輸出:
        spring容器啟動...
        person的無參構造器方法...
        person的初始化方法
        spring容器啟動成功!
        關閉spring容器...
        person的銷毀方法
        關閉spring容器成功!

2.當是多例模式
    2.1ioc的配置文件
            <bean id="person" class="entity.Person"
                  scope="prototype"---------------------------->多例模式
                  init-method="initMethod"
                  destroy-method="destroyMethod"
            >
            </bean>
        測試代碼:
            public static void main(String[] args) {
                System.out.println("spring容器啟動...");
                ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
                System.out.println("spring容器啟動成功!");
                System.out.println("關閉spring容器...");
                ioc.close();
                System.out.println("關閉spring容器成功!");
            }
        輸出:
            spring容器啟動...
            spring容器啟動成功!
            關閉spring容器...
            關閉spring容器成功!
        因為多例模式不是容器啟動的時候創創建,而是在ioc.getBean("id")時候創建該對象!
   
     2.2當測試代碼為:
            public static void main(String[] args) {
                System.out.println("spring容器啟動...");
                ConfigurableApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
                System.out.println("spring容器啟動成功!");
                ioc.getBean("person");------------------------>多例模式獲取bean對象
                System.out.println("關閉spring容器...");
                ioc.close();
                System.out.println("關閉spring容器成功!");
            }
        輸出:
            spring容器啟動...
            spring容器啟動成功!
            person的無參構造器方法...
            person的初始化方法
            關閉spring容器...
            關閉spring容器成功!
            
結論:
    1.當是單例模式時:Bean的生命周期
        (容器啟動)構造器方法---->初始化方法----->(容器關閉)銷毀方法
    2.多實例
        獲取bean(構造器------>初始化方法---->容器關閉(不會調用銷毀方法))

 

9.Bean的後置處理器

1.自定義一個類實現BeanPostProcessor介面
    public class MyBeanPostProcess  implements BeanPostProcessor {
    /**
     * 自定義的初始化方法之前調用
     * Object o是容器創建的bean
     * String s是spring配置文件中配置的id
     */
    public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
        System.out.println("bean的後置處理器Befor...方法");
        System.out.println(s+":"+o);
        return o;----->註意:這裡不能return null,要不會報錯
    }
    //自定義初始化方法之後執行  
    public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
        System.out.println("bean的後置處理器After...方法");
        System.out.println(s+":"+o);
        return o;------------------------->註意:這裡如果return null;則ioc.getBean也是為null;
    }
}
2.在spring配置文件中配置後置處理器
    <!--實體類配置-->
    <bean id="person01" class="entity.Person" 
         init-method="initMethod"----------------------->perosn類的自定義初始化方法(person實例化時後會調用)
         destroy-method="destroyMethod">----------------->person類的自定義銷毀方法(spring容器銷毀前會調用)
        <property name="age" value="18"></property>
        <property name="name" value="吳孟達"></property>
    </bean>
    <!--後置處理器配置-->
    <bean id="myBeanPostProcess" class="Test.MyBeanPostProcess"></bean>
3.測試代碼如下:
    public static void main(String[] args) {
        System.out.println("載入spring....");
        ApplicationContext ioc=new ClassPathXmlApplicationContext("ioc.xml");
        System.out.println("spring容器啟動成功!");
        Object bean= ioc.getBean("person01");
        System.out.println("容器獲取的bean:"+bean);
    }
4.輸出:
    person執行無參構造器
    person執行set age方法
    person執行set name方法
    bean的後置處理器Befor...方法
    person01:Person{name='吳孟達', age=18, book=null}
    person自定義的初始化方法
    bean的後置處理器After...方法
    person01:Person{name='吳孟達', age=18, book=null}
    spring容器啟動成功!
    容器獲取的bean:Person{name='吳孟達', age=18, book=null}
結論:
    發現帶後置處理器的執行流程如下:        

執行順序:

  • 1.bean實例化
  • 2.執行bean的後置處理器的postProcessBeforeInitialization方法
  • 3.執行自定義的初始化方法
  • 4.執行bean後置處理器的postProcessAfterInitialization方法


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 前言 本篇是以 HarmonyOS 官網的基於 TS 擴展的聲明式開發範式文檔,頁面佈局與連接為基礎進行編寫。儘管原篇已非常精簡,但是作為初學者想要快速入門,使用 ets 方式實現出 List 佈局、Grid 佈局、數據連接及頁面跳轉功能,還是稍顯晦澀。所以筆者將原文進行整合,提取出其中的要點,以便 ...
  • 隨著市場愈發成熟,開發者從平衡收益和風險的角度開始逐步探索混合變現的優勢,內購+廣告就是目前市場上混合變現的主要方式之一。 對於混合變現模式,您是否有這樣的困惑: 如何判斷哪些用戶更願意看廣告、哪些用戶付費意願更高,更好地平衡內購和廣告? 在提升整體收入的基礎上,怎樣為用戶提供更好的產品體驗? HM ...
  • 問題描述: 工作中碰到這樣一種場景, WebApp 已經實現了IM即時通訊及基於WebRTC實現的音視頻會議,音視頻聊天。 也是半路接手的項目,項目整體是使用WKWebView套殼載入h5 頁面實現(後期過審還有很多路要走) 。 h5與原生交互的方案使用的javascriptCore(具體如何使用, ...
  • 今天的內容vue腳手架,越來越有內味了,也慢慢地開始有點難度了哈哈,但是沒有關係,慢慢學慢慢琢磨,我倒是感覺有點越來越像node了,不知道怎麼回事,這是要向後端發展的節奏啊 一.初始化Vue腳手架 1.說明 一般腳手架選擇最新版本 2.具體步驟 全局安裝vue/cli腳手架 切換到項目目錄,運行 v ...
  • 常用函數封裝 獲取某日期若幹個工作日後的日期 * 參數: * time: [String] 給定日期 yyyy-MM-dd * itervalByDay: [Number] 相隔工作日 * separator: [String] 年月日分隔符 * 返回: * rq:[String] 匹配的日期yyy ...
  • 某日,群里有這樣一個問題,如何實現這樣的表盤刻度: 這其實是個挺有意思的問題,方法也有很多。 單標簽,使用 conic-gradient 實現表盤刻度 最簡單便捷的方式,就是利用角向漸變的方式 conic-gradient,代碼也非常簡單,首先,我們實現一個重覆角向漸變: <div></div> d ...
  • 今天是對vue組件化的一個理解,最主要的單文件組件,然後就可以腳手架的學習了,本來昨晚就該上傳的,但是用的那個上傳博客園的Python腳本不行了,換了一個新的。 組件化讓我越來越感覺到框架的力量了 一.模塊與組件,模塊化與組件化 1.對組件的理解 如果以我們原來編寫一個網頁的方式 依賴關係混亂我就不 ...
  • 1.基本介紹 1.1.概念 高層模塊不能依賴於一個“具體化、細節化”的低層模塊,而是通過一個抽象的“規範/標準”建立兩者之間的依賴關係,簡言之就是:不依賴於實現,而是依賴於抽象。這裡“實現”一詞有的地方也稱為“細節”,在編碼中主要體現的是我們根據業務模型具體自定義的普通類,比如:員工類、商品類等。而 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...