Spring框架第二篇之Bean的裝配

来源:http://www.cnblogs.com/Dylansuns/archive/2017/06/18/7042286.html
-Advertisement-
Play Games

一、預設裝配方式 代碼通過getBean();方式從容器中獲取指定的Bean實例,容器首先會調用Bean類的無參構造器,創建空值的實例對象。 舉例: 首先我在applicationContext.xml配置文件中配置了一個bean: 創建SomeServiceImpl對象,但需要註意的是該類的只具有 ...


一、預設裝配方式

代碼通過getBean();方式從容器中獲取指定的Bean實例,容器首先會調用Bean類的無參構造器,創建空值的實例對象。

舉例:

首先我在applicationContext.xml配置文件中配置了一個bean:

<?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">

    <!-- 註冊Service 這裡相當於容器做了SomeServiceImpl myService = new SomeServiceImpl(); -->
    <bean id="myService" class="com.ietree.spring.basic.ioc.SomeServiceImpl"/>
    
</beans>

創建SomeServiceImpl對象,但需要註意的是該類的只具有帶參構造函器,沒有無參構造器:

package com.ietree.spring.basic.ioc;

/**
 * 實現類
 * 
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {

    private int a;
    
    // 這裡註釋掉了無參構造函數,希望容器通過帶參構造函數創建對象
//    public SomeServiceImpl() {
//        System.out.println("執行無參構造器,創建SomeServiceImpl對象");
//    }

    public SomeServiceImpl(int a) {
        this.a = a;
    }

    @Override
    public void doSomeThing() {
        System.out.println("執行doSomeThing()方法...");
    }

}

測試:

@Test
public void testConstructor() {

    // 創建容器對象,載入Spring配置文件
    // ClassPathXmlApplicationContext會從類路徑下查找配置文件
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    ISomeService service = (ISomeService) ac.getBean("myService");
    service.doSomeThing();
}

此時程式會報以下的錯誤:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myService' defined in class path resource [applicationContext.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ietree.spring.basic.ioc.SomeServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.ietree.spring.basic.ioc.SomeServiceImpl.<init>()
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1155)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1099)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:513)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:483)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:761)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:867)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:543)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at com.ietree.spring.basic.test.MyTest.testConstrutor(MyTest.java:67)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.lang.reflect.Method.invoke(Unknown Source)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:678)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.ietree.spring.basic.ioc.SomeServiceImpl]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.ietree.spring.basic.ioc.SomeServiceImpl.<init>()
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:85)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1147)
    ... 36 more
Caused by: java.lang.NoSuchMethodException: com.ietree.spring.basic.ioc.SomeServiceImpl.<init>()
    at java.lang.Class.getConstructor0(Unknown Source)
    at java.lang.Class.getDeclaredConstructor(Unknown Source)
    at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:80)
    ... 37 more

解析:這裡的錯誤報的很明顯,沒有發現預設的構造器。

修改:為該類加上無參構造器:

package com.ietree.spring.basic.ioc;

/**
 * 實現類
 * 
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {

    private int a;
    
    public SomeServiceImpl() {
        System.out.println("執行無參構造器,創建SomeServiceImpl對象");
    }

    public SomeServiceImpl(int a) {
        this.a = a;
    }

    @Override
    public void doSomeThing() {
        System.out.println("執行doSomeThing()方法...");
    }

}

此時,再次運行測試用例,會發現運行成功。

結論:Spring容器實際上是使用了類的反射機制,會首先調用Bean類的無參構造器創建實例對象。

二、動態工廠Bean

 創建SomeServiceImpl類:

package com.ietree.spring.basic.ioc;

/**
 * 實現類
 * 
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {

    public SomeServiceImpl() {
        System.out.println("執行無參構造器,創建SomeServiceImpl對象");
    }

    @Override
    public void doSomeThing() {
        System.out.println("執行doSomeThing()方法...");
    }

}

創建工廠類ServiceFactory:

package com.ietree.spring.basic.ioc;

/**
 * 工廠類
 * 
 * @author Root
 */
public class ServiceFactory {

    public ISomeService getSomeService() {
        return new SomeServiceImpl();
    }

}

使用動態工廠方式獲取Bean對象,配置如下:

<?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">

    <!-- 註冊動態工廠 -->
    <bean id="factory" class="com.ietree.spring.basic.ioc.ServiceFactory"/>
    
    <!-- 註冊Service:動態工廠Bean -->
    <bean id="myService" factory-bean="factory" factory-method="getSomeService"/>
    
</beans>

在這裡並沒有註冊SomeServiceImpl類,而是通過ServiceFactory工廠的getSomeService方法獲取的。

測試:

@Test
public void testFactory1() {
        
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    ISomeService service = (ISomeService) ac.getBean("myService");
    service.doSomeThing();
}

運行成功。

三、靜態工廠Bean

 靜態工廠和動態工廠不同的是,靜態工廠中使用的是靜態方法創建對象,如:

package com.ietree.spring.basic.ioc;

/**
 * 工廠類
 * 
 * @author Root
 */
public class ServiceFactory {
    
    // 使用靜態方法創建對象
    public static ISomeService getSomeService() {
        return new SomeServiceImpl();
    }

}

對應的配置文件修改如下:

<?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">

    <!-- 註冊Service:靜態工廠Bean -->
    <bean id="myService" class="com.ietree.spring.basic.ioc.ServiceFactory" factory-method="getSomeService"/>
    
</beans>

測試:

@Test
public void testFactory1() {
        
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
    ISomeService service = (ISomeService) ac.getBean("myService");
    service.doSomeThing();
}

成功創建SomeServiceImpl對象。

四、容器中的Bean的作用域

 Bean的作用域(scope)分為四種,分別是singleton、prototype、request、session。

scope:
  singleton(預設):單例模式,其對象的創建時機是在Spring容器初始化時創建,是預設值
  prototype:原型模式,其對象的創建時機不是在Spring容器初始化時創建,而是在代碼中真正訪問時才創建,每次使用getBean方法獲取的同一個<bean/>的實例都是一個新的實例
  request:對於每次HTTP請求,都將會產生一個不同的Bean實例
  session:對於每個不同的HTTP session,都將會產生一個不同的Bean實例

驗證:

首先配置作用域為singleton:

<bean id="myService" class="com.ietree.spring.basic.ioc.SomeServiceImpl" scope="singleton"/>

測試:

@Test
public void test05() {
        
    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
    ISomeService service1 = (ISomeService) ac.getBean("myService");
    ISomeService service2 = (ISomeService) ac.getBean("myService");
    System.out.println("service1 = service2嗎?" + (service1 == service2));
}

程式輸出:

調用無參構造器
service1 = service2嗎?true

結論:當作用域為singleton單例模式時,只會創建一個對象實例,並且對象是在Spring容器初始化時創建。

同樣,當配置為prototype原型模式時:

<bean id="myService" class="com.ietree.spring.basic.ioc.SomeServiceImpl" scope="prototype"/>

程式輸出:

調用無參構造器
調用無參構造器
service1 = service2嗎?false

結論:構造器被調用了兩次,說明創建的service1和service2不是同一個對象,並且對象是在被使用到時才創建的。

五、Bean後處理器

 Bean後處理器是一種特殊的Bean,容器中所有的Bean在初始化時,均會自動執行該類的兩個方法。由於該Bean是由其它Bean自動調用執行,不是程式員手工調用,故此Bean無須id屬性。

需要做的是,在Bean後處理器類方法中,只要對Bean類與Bean類中的方法進行判斷,就可實現對指定的Bean的指定的方法進行功能擴展與增強。方法返回的Bean對象,即是增強過的對象。

代碼中需要自定義Bean後處理器類,該類就是實現了介面BeanPostProcessor的類。該介面中包含兩個方法,分別在目標Bean初始化完畢之前與之後執行,它的返回值為功能被擴展或增強後的Bean對象。

舉例:利用Bean後處理器實現大小寫字元串轉換

介面類ISomeService:

/**
 * 介面類
 * 
 * @author Root
 */
public interface ISomeService {
    
    String doSomeThing();
    
}

實現類SomeServiceImpl:

/**
 * 實現類
 * 
 * @author Root
 */
public class SomeServiceImpl implements ISomeService {

    public SomeServiceImpl() {
        System.out.println("調用無參構造器");
    }
    
    // 返回小寫字母“abcde”
    @Override
    public String doSomeThing() {
        return "abcde";
    }
}

定義Bean處理器MyBeanPostProcessor:

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Bean後處理器
 * 
 * @author Root
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    // bean:表示當前正在進行初始化的Bean對象
    // beanName:表示當前正在進行初始化的Bean對象的id
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("執行----before()方法---");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("執行----after()方法---");

        Object obj = Proxy.newProxyInstance(
                bean.getClass().getClassLoader(), 
                bean.getClass().getInterfaces(),
                new InvocationHandler() {

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

                        Object invoke = method.invoke(bean, args);

                        return ((String) invoke).toUpperCase();
                    }
                });
        return obj;
    }

}

使用JDK動態代理實現大小寫轉換的功能。

配置文件:

<bean id="myService" class="com.ietree.spring.basic.ioc.method2.SomeServiceImpl"/>
    
<!-- 註冊Bean後處理器,由於該Bean是由其它Bean自動調用執行,不是程式員手工調用,故此Bean無須id屬性 -->
<bean class="com.ietree.spring.basic.ioc.method2.MyBeanPostProcessor"></bean>

註意:Bean後處理器不需要配置id的,因為它是隨著對象的創建自動調用的。

測試:

@Test
public void test05() {

    ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");

    ISomeService service = (ISomeService) ac.getBean("myService");
    String result = service.doSomeThing();
    System.out.println(result);
}

程式輸出:

調用無參構造器
執行----before()方法---
執行----after()方法---
ABCDE

增強成功。可以判斷代理類的類型,進行對單個或單獨一類對象做增強。

六、定製Bean的生命周期

 Bean實例從創建到最後銷毀,需要經過很多過程,執行很多生命周期方法。

Step1:調用無參構造器,創建實例對象。

Step2:調用參數的setter,為屬性註入值。

Step3:若Bean實現了BeanNameAware介面,則會執行介面方法setBeanName(String beanId),使Bean類可以獲取其在容器中的id名稱。

Step4:若Bean實現了BeanFactoryAware介面,則執行介面方法setBeanFactory(BeanFactory factory),使Bean類可以獲取到BeanFactory對象。

Step5:若定義並註冊了Bean後處理器BeanPostProcessor,則執行介面方法postProcessBeforeInitialization()。

Step6:若Bean實現了InitializingBean介面,則執行介面方法afterPropertiesSet()方法。該方法在Bean的所有屬性的set方法執行完畢後執行,是Bean初始化結束的標誌,即Bean實例化結束。

Step7:若設置了init-method方法,則執行。

Step8:若定義並註冊了Bean後處理器BeanPostProcessor,則執行介面方法postProcessAfterInitialization().

Step9:執行業務方法。

Step10:若Bean實現了DisposableBean介面,則執行介面方法destroy()。

Step11:若設置了destroy-method方法,則執行。

舉例:

創建介面類ISomeService:

/**
 * 介面類
 * 
 * @author Root
 */
public interface ISomeService {
    
    void doSomeThing();
    
}

創建介面實現類SomeServiceImpl:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

/**
 * 實現類
 * 
 * @author Root
 */
public class SomeServiceImpl implements ISomeService, BeanNameAware, BeanFactoryAware, InitializingBean, DisposableBean {
    
    // 兩個屬性
    private String adao;
    private String bdao;
    
    public void setAdao(String adao) {
        this.adao = adao;
        System.out.println("Step2:執行settter");
    }

    public void setBdao(String bdao) {
        this.bdao = bdao;
        System.out.println("Step2:執行settter");
    }

    public SomeServiceImpl() {
        System.out.println("Step1:調用無參構造器");
    }
    
    @Override
    public void doSomeThing() {
        System.out.println("Step9:執行doSomeThing()");
    }
    
    public void setUp(){
        System.out.println("Step7:初始化完畢之後 ");
    }
    
    public void tearDown(){
        System.out.println("Step11:銷毀之前");
    }

    @Override
    public void setBeanName(String name) {
        System.out.println("Step3:獲取到bean的id = " + name);
    }

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("Step4:獲取到BeanFactory容器 ");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("Step6:Bean初始化完畢了 ");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("Step10:實現的介面銷毀之前 ");
    }
}

創建BeanPostProcessor介面的實現類MyBeanPostProcessor:

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * Bean後處理器
 * 
 * @author Root
 */
public class MyBeanPostProcessor implements BeanPostProcessor {

    // bean:表示當前正在進行初始化的Bean對象
    // beanName:表示當前正在進行初始化的Bean對象的id
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Step5:執行----before()方法---");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Step8:執行----after()方法---");
        return bean;
    }

}

配置applicationContext.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">

    <!-- 註冊Service -->
    <bean id="myService" class="com.ietree.spring.basic.ioc.method3.SomeServiceImpl" init-method="setUp" destroy-method="tearDown">
        <property name="adao" value="aaa"></property>
        <property name="bdao" value="bbb"></property>
    </bean>
    
    <!-- 註冊Bean後處理器,由於該Bean是由其它Bean自動調用執行,不是程式員手工調用,故此Bean無須id屬性 -->
    <bean class="com.ietree.spring.basic.ioc.method3.MyBeanPostProcessor"></bean>

</beans>

測試類:

@Test
public void test05() {

    String resource = "com/ietree/spring/basic/ioc/method3/applicationContext.xml";
    ApplicationContext ac = new ClassPathXmlApplicationContext(resource);

    ISomeService service = (ISomeService) ac.getBean("myService");
    service.doSomeThing();
    // 對於銷毀方法的執行,有兩個條件:
    // 1)當前的Bean需要是singleton的
    // 2)要手工關閉容器
    ((ClassPathXmlApplicationContext) ac).close();
}

程式輸出:

Step1:調用無參構造器
Step2:執行settter
Step2:執行settter
Step3:獲取到bean的id = myService
Step4:獲取到BeanFactory容器 
Step5:執行----before()方法---
Step6:Bean初始化完畢了 
Step7:初始化完畢之後 
Step8:執行----after()方法---
Step9:執行doSomeThing()
Step10:實現的介面銷毀之前 
Step11:銷毀之前

正如程式輸出的序列一樣,此順序即是對象創建的調用順序,在編程中可以在某一個過程對其進行增強操作。

七、<bean/>標簽的id屬性與name屬性

 一般情況下,命名<bean/>使用id屬性,而不是用name屬性,在沒有id屬性的情況下,name屬性與id屬性作用是相同的。但,當<bean/>中含有一些特殊字元時,就需要使用name屬性了。

id的命名需要滿足XML對ID屬性命名規範:必須以字母開頭,可以包含字母、數字、下劃線、連字元、句號、冒號。

name屬性值可以包含各種字元。


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

-Advertisement-
Play Games
更多相關文章
  • 代碼: private string GetImageExtension(MemoryStream ms) { try { Image image = Image.FromStream(ms); if (image.RawFormat.Guid == ImageFormat.Bmp.Guid) re ...
  • 版權聲明:本文為原創文章,轉載請聲明http://www.cnblogs.com/unityExplorer/p/7027659.html 上篇已經把socket的傳輸說的差不多了,這篇主要是說說斷線重連,沒什麼好說的,直接上代碼吧 ...
  • 遇到一個奇怪的問題 ,只然訪問到Index的action,訪問其它的都報404錯 ,在Windows的IIS上則不會有此問題 如 正常 http://localhost:5000/login/index 報404錯誤 http://localhost:5000/login/test 經查是Start ...
  • 要求是這樣子的,在一個列表頁中,用戶點擊詳細銨鈕,帶記錄的主鍵值至另一頁。在另一外頁中,獲取記錄數據,然後顯示此記錄數據在網頁上。先用動圖演示: 昨天有分享為ng-click傳遞參數 《angularjs為ng-click事件傳遞參數》http://www.cnblogs.com/insus/p/7 ...
  • Java中的wait/notify/notifyAll可用來實現線程間通信,是Object類的方法,這三個方法都是native方法,是平臺相關的,常用來實現生產者/消費者模式。先來我們來看下相關定義: wait() :調用該方法的線程進入WATTING狀態,只有等待另外線程的通知或中斷才會返回,調用 ...
  • 第九節 函數 函數就是完成特定功能的一個語句組,這組語句可以作為一個單位使用,並且給它取一個名字。 可以通過函數名在程式的不同地方多次執行(這通常叫做函數調用),卻不需要在所有地方都重覆編寫這些語句。 自定義函數 用戶自己編寫的 預定義的Python函數 系統自帶的一些函數,還有一些和第三方編寫的函 ...
  • ActiveMQ支持的client-broker通訊協議有:TCP、NIO、UDP、SSL、Http(s)、VM。 其中配置Transport Connector的文件在activeMQ安裝目錄的conf/activemq.xml中的 ...
  • extract images from video, than save them to disk from moviepy.editor import VideoFileClip clip1 = VideoFileClip('./project_video.mp4') i = 1 for fram ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...