Spring源碼系列(一)–詳細介紹bean組件

簡介

spring-bean 組件是 Spring IoC 的核心,我們可以使用它的 beanFactory 來獲取所需的對象,對象的實例化、屬性裝配和初始化等都可以交給 spring 來管理。

針對 spring-bean 組件,我計劃分成兩篇博客來講解。本文會詳細介紹這個組件,包括以下內容。下一篇再具體分析它的源碼。

  1. spring-bean 組件的相關概念:實例化、屬性裝配、初始化、bean、beanDefinition、beanFactory。
  2. bean 組件的使用:註冊bean、獲取bean、屬性裝配、處理器等。

項目環境說明

正文開始前,先介紹下示例代碼使用的環境等。

工程環境

JDK:1.8.0_231

maven:3.6.1

IDE:Spring Tool Suites4 for Eclipse 4.12

Spring:5.2.6.RELEASE

依賴引入

除了引入 spring,這裏還額外引入了日誌和單元測試。

    <properties>
        <spring.version>5.2.6.RELEASE</spring.version>
    </properties>
    
    <dependencies>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
		<!-- junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- logback -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.28</version>
            <type>jar</type>
            <scope>compile</scope>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.2.3</version>
            <type>jar</type>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.2.3</version>
            <type>jar</type>
        </dependency>
    </dependencies>

幾個重要概念

實例化、屬性裝配和初始化

在 spring-bean 組件的設計中,這三個詞完整、有序地描述了生成一個新對象的整個流程,是非常重要的理論基礎。它們的具體含義如下:

  1. 實例化:創建出一個新對象。
  2. 屬性裝配:給對象的成員屬性賦值。
  3. 初始化:調用對象的初始化方法。

下面使用一段代碼來簡單演示下這個流程。

public class UserService implements IUserService {
    
    private UserDao userDao;
    
    
    public UserService() {
        super();
        System.err.println("UserService構造方法被調用");
        System.err.println("        ||");
        System.err.println("        \\/");
    }
    
    public void init() {
        System.err.println("UserService的init方法被調用");
        System.err.println("        ||");
        System.err.println("        \\/");
    }
    
    
    public UserDao getUserDao() {
        return userDao;
    }
    
    public void setUserDao(UserDao userDao) {
        System.err.println("UserService的屬性裝配中");
        System.err.println("        ||");
        System.err.println("        \\/");
        this.userDao = userDao;
    }
    
}

如果我們將這個 bean 交給 spring 管理,獲取 bean 時會在控制台打印以下內容:

什麼是bean

按照官方的說法, bean 是一個由 Spring IoC 容器實例化、組裝和管理的對象。我認為,這種表述是錯誤的,通過registerSingleton方式註冊的 bean,它就不是由 Spring IoC 容器實例化、組裝,所以,更準確的表述應該是這樣:

某個類的對象、FactoryBean 對象、描述對象或 FactoryBean 描述對象,被註冊到了 Spring IoC 容器,這時通過 Spring IoC 容器獲取的這個類的對象就是 bean。

舉個例子,使用了 Spring 的項目中, Controller 對象、Service 對象、DAO 對象等都屬於 bean。

至於什麼是 IoC 容器,在 spring-bean 組件中,我認為,beanFactory 就屬於 IoC 容器。

什麼是beanFactory

從客戶端來看,一個完整的 beanFactory 工廠包含以下基本功能:

  1. 註冊別名。對應下圖的AliasRegistry接口。
  2. 註冊單例對象。對應下圖的SingletonBeanRegistry接口。
  3. 註冊BeanDefinition對象。對應下圖的BeanDefinitionRegistry接口。
  4. 獲取 bean。對應下圖的BeanFactory接口。

在 spring-bean 組件中,DefaultListableBeanFactory就是一個完整的 beanFactory 工廠,也可以說是一個 IoC 容器。接下來的例子將直接使用它來作為 beanFactory。

至於其他的接口,這裏也補充說明下。HierarchicalBeanFactory用於提供父子工廠的支持,ConfigurableBeanFactory用於提供配置 beanFactory 的支持,ListableBeanFactory用於提供批量獲取 bean 的支持(不包含父工廠的 bean),AutowireCapableBeanFactory用於提供實例化、屬性裝配、初始化等一系列管理 bean 生命周期的支持。

什麼是beanDefinition

beanDefinaition 是一個描述對象,用來描述 bean 的實例化、初始化等信息。

在 spring-bean 組件中,beanDefinaition主要包含以下四種:

  1. RootBeanDefinition:beanFactory 中最終用於 createBean 的 beanDefinaition,不允許添加 parentName。在 BeanFactory 中以下三種實現類都會被包裝成RootBeanDefinition用於 createBean。
  2. ChildBeanDefinition:必須設置 parentName 的 beanDefinaition。當某個 Bean 的描述對象和另外一個的差不多時,我們可以直接定義一個ChildBeanDefinition,並設置它的 parentName 為另外一個的 beanName,這樣就不用重新設置一份。
  3. GenericBeanDefinition:通用的 beanDefinaition,可以設置 parentName,也可以不用設置。
  4. AnnotatedGenericBeanDefinition:在GenericBeanDefinition基礎上增加暴露註解數據的方法。

spring-bean 組件提供了BeanDefinitionBuilder用於創建 beanDefinaition,下面的例子會頻繁使用到。

使用例子

入門–簡單地註冊和獲取bean

下面通過一個入門例子來介紹註冊和獲取 bean 的過程。

    @Test
    public void testBase() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        
        // 創建BeanDefinition對象
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        
        // 註冊Bean
        beanFactory.registerBeanDefinition("userService", rootBeanDefinition);
        
        // 獲取Bean
        IUserService userService = (IUserService)beanFactory.getBean("userService");
        System.err.println(userService.get("userId"));
    }

兩種註冊bean的方式

beanFactory 除了支持註冊 beanDefinition,還允許直接註冊 bean 實例,如下。和前者相比,後者的實例化、屬性裝配和初始化都沒有交給 spring 管理。

    @Test
    public void testRegisterWays() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        
        // 註冊Bean-- BeanDefinition方式
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("userService", rootBeanDefinition);
        
        // 註冊Bean-- Bean實例方式
        beanFactory.registerSingleton("userService2", new UserService());
        
        // 獲取Bean
        IUserService userService = (IUserService)beanFactory.getBean("userService");
        System.err.println(userService.get("userId"));
        IUserService userService2 = (IUserService)beanFactory.getBean("userService2");
        System.err.println(userService2.get("userId"));
    }

當然,這種方式僅支持單例 bean 的註冊,多例的就沒辦法了。

註冊多例bean

默認情況下,我們從 beanFactory 獲取到的 bean 都是單例的,即每次 getBean 獲取到的都是同一個對象,實際項目中,有時我們需要獲取到多例的 bean,這個時候就可以通過設置 beanDefinition 的 scope 來處理。如下:

    @Test
    public void testScope() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        
        // 註冊Bean-- BeanDefinition方式
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        rootBeanDefinition.setScope(BeanDefinition.SCOPE_PROTOTYPE);
        beanFactory.registerBeanDefinition("userService", rootBeanDefinition);
        
        // 獲取Bean--通過BeanType
        IUserService userService1 = beanFactory.getBean(IUserService.class);
        IUserService userService2 = beanFactory.getBean(IUserService.class);
        assertNotEquals(userService1, userService2);
    }

多種獲取bean的方式

beanFactory 提供了多種方式來獲取 bean 實例,如下。如果同時使用 beanName 和 beanType,獲取到指定 beanName 的 bean 後會進行類型檢查和類型類型,如果都不通過,將會報錯。

    @Test
    public void testGetBeanWays() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        
        // 創建BeanDefinition對象
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        
        // 註冊Bean
        beanFactory.registerBeanDefinition("userService", rootBeanDefinition);
        
        // 獲取Bean--通過BeanName
        IUserService userService = (IUserService)beanFactory.getBean("userService");
        System.err.println(userService.get("userId"));
        // 獲取Bean--通過BeanType
        IUserService userService2 = beanFactory.getBean(IUserService.class);
        System.err.println(userService2.get("userId"));
        // 獲取Bean--通過BeanName+BeanType的方式
        IUserService userService3 = beanFactory.getBean("userService", IUserService.class);
        System.err.println(userService3.get("userId"));
    }

不同形式的beanName

通過 name 獲取 bean,這個 name 包含以下三種形式:

  1. beanName,即註冊 bean 時用的 beanName。這是使用最多的形式,需要注意一點,如果 beanName 對應的 bean 是FactoryBean,並不會返回FactoryBean的實例,而是會返回FactoryBean.getObject方法的返回結果。
  2. alias,即我們通過SimpleAliasRegistry.registerAlias(name, alias)方法註冊到 beanFactory 的別名。這時,需要將 name 解析為 alias 對應的 beanName 來獲取 bean。
  3. ‘&’ + factorybeanName,這時為了獲取FactoryBean的一種特殊格式。
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 註冊Bean--註冊的是一個 FactoryBean
        UserServiceFactoryBean userServiceFactoryBean = new UserServiceFactoryBean();
        beanFactory.registerSingleton("userServiceFactoryBean", userServiceFactoryBean);

        // 註冊BeanName的別名
        beanFactory.registerAlias("userServiceFactoryBean", "userServiceAlias01");

        // 通過BeanName獲取
        assertEquals(userServiceFactoryBean.getObject(), beanFactory.getBean("userServiceFactoryBean"));

        // 通過別名獲取
        assertEquals(userServiceFactoryBean.getObject(), beanFactory.getBean("userServiceAlias01"));

        // 通過&+FactoryBeanName的方式
        assertEquals(userServiceFactoryBean, beanFactory.getBean("&userServiceFactoryBean"));

bean衝突的處理

通過 beanType 的方式獲取 bean,如果存在多個同類型的 bean且無法確定最優先的那一個,就會報錯。

    @Test
    public void testPrimary() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory(); 
        
        // 創建BeanDefinition對象
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        
        // 註冊Bean
        beanFactory.registerBeanDefinition("UserRegisterBeanDefinition", rootBeanDefinition);
        beanFactory.registerSingleton("UserRegisterSingleton", new User("zzs002", 19));
        beanFactory.registerSingleton("UserRegisterSingleton2", new User("zzs002", 18));
        
        // 獲取Bean--通過BeanType
        User user = beanFactory.getBean(User.class);
        System.err.println(user);
    }

運行以上方法,將出現 NoUniqueBeanDefinitionException 的異常。

針對上面的這種問題,spring 的處理方法如下:

  1. 檢查是否存在唯一一個通過registerBeanDefinition且isPrimary = true的(存在多個會報錯),存在的話將它作為匹配到的唯一 beanName;
  2. 通過我們註冊的OrderComparator來確定優先值最小的作為唯一 beanName。注意,通過registerSingleton註冊的和通過registerBeanDefinition註冊的,比較的對象是不一樣的,前者比較的對象是 bean 實例,後者比較的對象是 bean 類型,另外,這種方法最好不要存在相同優先級的 bean。

所以,為了解決這種衝突,可以設置BeanDefinition對象的 isPrimary = true,或者為 beanFactory 設置OrderComparator,代碼如下:

    @Test
    public void testPrimary() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 為BeanFactory設置比較器
        beanFactory.setDependencyComparator(new OrderComparator() {

            @Override
            public Integer getPriority(Object obj) {
                return obj.hashCode();
            }
        });

        // 創建BeanDefinition對象
        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        // rootBeanDefinition.setPrimary(true); // 設置BeanDefinition對象為isPrimary

        // 註冊Bean
        beanFactory.registerBeanDefinition("userRegisterBeanDefinition", rootBeanDefinition);
        beanFactory.registerSingleton("userRegisterSingleton", new User("zzs002", 19));
        beanFactory.registerSingleton("userRegisterSingleton2", new User("zzs003", 18));

        // 獲取Bean--通過BeanType
        User user = beanFactory.getBean(User.class);
        System.err.println(user);
    }

使用TypeConverter獲取自定義類型的對象

當我們使用 beanType 來獲取 bean 時,如果獲取到的 bean 不是指定的類型,這時,不會立即報錯,beanFactory 會嘗試使用我們註冊的TypeConverter來強制轉換。而這個類型轉換器我們可以自定義設置,如下。

    @Test
    public void testTypeConverter() {
        
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        // 註冊類型轉換器
        beanFactory.setTypeConverter(new TypeConverterSupport() {
            @SuppressWarnings("unchecked")
            @Override
            public <T> T convertIfNecessary(@Nullable Object value, @Nullable Class<T> requiredType,
                    @Nullable TypeDescriptor typeDescriptor) throws TypeMismatchException {
                // 將User轉換為UserVO
                if(UserVO.class.equals(requiredType) && User.class.isInstance(value)) {
                    User user = (User)value;
                    return (T)new UserVO(user);
                }
                return null;
            }
        });

        BeanDefinition rootBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(User.class).getBeanDefinition();
        beanFactory.registerBeanDefinition("User", rootBeanDefinition);

        UserVO bean = beanFactory.getBean("User", UserVO.class);
        Assert.assertTrue(UserVO.class.isInstance(bean));
    }

屬性裝配

beanFactory 在進行屬性裝配時,會讀取 beanDefinition 對象中的PropertyValues中的propertyName=propertyValue,所以,我們想要對 bean 注入什麼參數,只要在定義 beanDefinition 時指定就行。

    @Test
    public void testPopulate() {
        // 創建BeanFactory對象
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 定義userService的beanDefinition
        AbstractBeanDefinition userServiceBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        // 定義userDao的beanDefinition
        AbstractBeanDefinition userDaoBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserDao.class).getBeanDefinition();
        // 給userService設置裝配屬性
        userServiceBeanDefinition.getPropertyValues().add("userDao", userDaoBeanDefinition);
        // userServiceBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_TYPE);
        // userServiceBeanDefinition.setAutowireMode(AbstractBeanDefinition.AUTOWIRE_BY_NAME);

        // 註冊Bean
        beanFactory.registerBeanDefinition("userService", userServiceBeanDefinition);
        beanFactory.registerBeanDefinition("userDao", userDaoBeanDefinition);

        // 獲取Bean
        IUserService userService = (IUserService)beanFactory.getBean("userService");
        userService.save(null);
    }

運行以上方法,發現 userDao 對象被成功注入到了 userService 對象中!

這裏補充一點,beanFactory 除了通過 beanDefinition 中的PropertyValues獲取 propertyName=propertyValue,還可以讀取 bean 中的屬性來自動定義 propertyName=propertyValue,只要設置 beanDefinition 的 autowireMode 就可以了。

bean 實例化、屬性裝配和初始化的處理器

前面講到,我們將 bean 的實例化、屬性裝配和初始化都交給了 spring 處理,然而,有時我們需要在這些節點對 bean 進行自定義的處理,這時就需要用到 beanPostProcessor。

這裏我簡單演示下如何添加處理器,以及處理器的執行時機,至於處理器的具體實現,我就不多擴展了。

    @Test
    public void testPostProcessor() {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        // 添加實例化處理器
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {
            // 如果這裏我們返回了對象,則beanFactory會將它作為bean直接返回,不再進行bean的實例化、屬性裝配和初始化等操作
            public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
                if(UserService.class.equals(beanClass)) {
                    System.err.println("bean實例化之前的處理。。 --> ");
                }
                return null;
            }

            // 這裏通過返回的布爾值判斷是否需要繼續對bean進行屬性裝配和初始化等操作
            public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
                if(UserService.class.isInstance(bean)) {
                    System.err.println("bean實例化之後的處理。。 --> ");
                }
                return true;
            }
        });

        // 添加裝配處理器
        beanFactory.addBeanPostProcessor(new InstantiationAwareBeanPostProcessor() {

            // 這裏可以在屬性裝配前對參數列表進行調整
            public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
                if(UserService.class.isInstance(bean)) {
                    System.err.println("屬性裝配前對參數列表進行調整 --> ");
                }
                return InstantiationAwareBeanPostProcessor.super.postProcessProperties(pvs, bean, beanName);
            }

        });

        // 添加初始化處理器
        beanFactory.addBeanPostProcessor(new BeanPostProcessor() {

            // 初始化前對bean進行改造
            public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
                if(UserService.class.isInstance(bean)) {
                    System.err.println("初始化前,對Bean進行改造。。 --> ");
                }
                return bean;
            }

            // 初始化后對bean進行改造
            public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
                if(UserService.class.isInstance(bean)) {
                    System.err.println("初始化后,對Bean進行改造。。 --> ");
                }
                return bean;
            }
        });
        // 定義userService的beanDefinition
        AbstractBeanDefinition userServiceBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserService.class).getBeanDefinition();
        // 定義userDao的beanDefinition
        AbstractBeanDefinition userDaoBeanDefinition = BeanDefinitionBuilder.rootBeanDefinition(UserDao.class).getBeanDefinition();
        // 給userService添加裝配屬性
        userServiceBeanDefinition.getPropertyValues().add("userDao", userDaoBeanDefinition);
        // 給userService設置初始化方法
        userServiceBeanDefinition.setInitMethodName("init");
        
        // 註冊bean
        beanFactory.registerBeanDefinition("userService", userServiceBeanDefinition);
        beanFactory.registerBeanDefinition("userDao", userDaoBeanDefinition);

        IUserService userService = (IUserService)beanFactory.getBean("userService");
        System.err.println(userService.get("userId"));
    }

運行以上方法,控制台打印出了整個處理流程。實際開發中,我們可以通過設置處理器來改變改造生成的 bean 。

以上,基本介紹完 spring-bean 組件的使用,下篇博客再分析源碼,如果在分析過程中發現有其他特性,也會在這篇博客的基礎上擴展。

相關源碼請移步: spring-beans

本文為原創文章,轉載請附上原文出處鏈接:https://www.cnblogs.com/ZhangZiSheng001/p/13126053.html

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※超省錢租車方案

※別再煩惱如何寫文案,掌握八大原則!

※回頭車貨運收費標準

※教你寫出一流的銷售文案?

※產品缺大量曝光嗎?你需要的是一流包裝設計!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

全球暖化影響北極圈 海冰覆蓋值降至40年來次低

摘錄自2020年9月21日中央社報導

北極圈氣候暖化導致覆蓋北極海的冰層大幅縮小,科學家21日表示,今年覆蓋值來到40年來第2低,為氣候變遷迅速改變北極地帶的另一個跡象。

路透社報導,美國國家冰雪資料中心(National Snow and Ice Data Center)研究人員說,根據衛星紀錄,今年度海冰面積最小值落在9月15日,只有374萬平方公里,是40年前有紀錄以來,海冰面積第2次低於400萬平方公里。

北極圈海冰覆蓋值最低紀錄為341萬平方公里,是在2012年一場季末氣旋風暴導致剩下的海冰解體後發生。受到西伯利亞熱浪產生的熱空氣影響,今年海冰在8月31日到9月5日這6天期間縮減速度之快,超越有紀錄以來任何一年。

氣候變遷
國際新聞
北極
全球暖化
冰層消融
海冰

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

不公平的碳足跡:全球前10%富人 25年來碳排放占世界一半

環境資訊中心綜合外電;姜唯 編譯;林大利 審校

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※別再煩惱如何寫文案,掌握八大原則!

※網頁設計最專業,超強功能平台可客製化

澳洲現代史上最慘集體擱淺 470頭領航鯨受困沙洲

摘錄自2020年9月23日中央社報導

大約270頭鯨魚21日被發現擱淺後,當局發起大型救援行動。那批鯨魚至少有90頭已經死亡,救援人員23日又發現200頭鯨魚擱淺在澳洲偏遠海港,3天下來,共有470頭受困沙洲,是澳洲現代史上最慘烈的鯨魚擱淺紀錄。

法新社與英國廣播公司(BBC)報導,塔斯馬尼亞州(Tasmania)環境部門女發言人指出,這些長肢領航鯨受困在西岸人口稀少的麥夸利港(Macquarie Harbour)兩處不同地點。「已經證實,又發現大約200頭先前沒被找到的鯨魚。」

1996年有320頭領航鯨擱淺在西澳州(Western Australia),是澳洲先前有大批鯨魚擱淺的最慘烈紀錄。

生物多樣性
海洋
國際新聞
澳洲
塔斯馬尼亞
鯨豚擱淺
領航鯨

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※想知道最厲害的網頁設計公司"嚨底家"!

※別再煩惱如何寫文案,掌握八大原則!

※產品缺大量曝光嗎?你需要的是一流包裝設計!

西伯利亞森林大火 科學家憂氣候變遷成惡性循環

摘錄自2020年9月24日自由時報報導

俄羅斯西伯利亞今年林火問題嚴重,外媒表示,嚴重的林火帶來的是惡性循環,一方面釋放更多的溫室氣體,接著又因氣候暖化使森林更容易發生火災。

《BBC中文網》報導,西伯利亞的森林大火釋放出破紀錄容量的碳。更大的危機在於火焰燃燒產生二氧化碳,且因為凍土被溶解而釋放更多溫室氣體,導致西伯利亞氣溫上升,森林因此更加乾燥,更容易燃燒,成為氣候變化的惡性循環。

報導指出,科學家認為森林大火正在產生極大量的溫室氣體,改變全球氣候。

氣候變遷
環境新聞
國際新聞
俄羅斯
森林大火
溫室氣體

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※別再煩惱如何寫文案,掌握八大原則!

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※超省錢租車方案

※教你寫出一流的銷售文案?

※網頁設計最專業,超強功能平台可客製化

※產品缺大量曝光嗎?你需要的是一流包裝設計!

對抗氣候變遷和空污 加州2035年起禁售新汽油車

摘錄自2020年9月24日中央社報導

加州州長紐松今天(24日)宣布,加州計劃自2035年起禁止販售新出廠的汽油驅動客車和卡車,逐步淘汰傳統汽車並轉向電動車,積極減輕對化石燃料依賴,以對抗氣候變遷和嚴重空污。

州長辦公室說,加州碳污染有一半以上來自交通運輸,州內有部分地區的空氣為全國最糟。加州的宏遠目標是以1990年為基準,在2050年前減少80%溫室氣體排放量,但近幾年來,交通運輸的碳排放量仍持續增加。

這項行政命令要求加州在2035年之前,全面銷售新出廠的零碳排客車和卡車;在2045年之前,所有新販售的中重型卡車也必須為零碳排車輛。

州長辦公室說,原本駕駛汽油車的加州居民不會受到影響,二手汽油車也可繼續買賣。加州占美國所有汽車銷量大約11%。

氣候變遷
污染治理
能源轉型
環境新聞
國際新聞
美國
加州
電動車
空污

本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※教你寫出一流的銷售文案?

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※回頭車貨運收費標準

※別再煩惱如何寫文案,掌握八大原則!

※超省錢租車方案

※產品缺大量曝光嗎?你需要的是一流包裝設計!

不到10萬還皮實耐用的大眾神車,車主用得順心?

4T/1。5L最大馬力(ps):90/110/131最大扭矩(Nm):132/150/225變速箱:5MT/6AT/7DCT驅動方式:前置前驅底盤懸挂:前麥弗遜獨立懸挂/后複合扭力梁式非獨立懸挂動力匹配方面,現款捷達還挺多選擇的,但是1。4T的車型基本不推薦,因為太貴了。

相信“捷達”這款車

早就已經不只是情懷和故事了

更多的是一種文化現象

而這種文化現象是一直在變的

就比如現款的捷達

也已經不是我們印象中那款

“方頭方腦”的大眾車了

但無論怎麼變

捷達的銷量依然很堅挺

那現在的捷達

就是我們還能買到的捷達

都有哪些魅力?

讓我們結合車主的口碑探討一波

長寬高:4501*1704*1469mm

軸距:2604mm

定位:緊湊型車

現款捷達的外觀早已一改過去“方頭方腦”的造型,套用了大眾全新的家族式設計語言,首先作為一輛大眾車,套娃式的家族前臉必不可少。或許許多有情懷的消費者還是會更喜歡捷達過去的造型,但那個造型已經不復存在了。雖然現在的捷達整體造型更飽滿了,但是那種低調務實的氣質仍然保留着,我想車主們對它的外觀最滿意的就是這點吧。

內飾設計依然很“大眾”,對於車主來說,捷達精湛的內飾做工也是一直以來讓人滿意的方面,設計以簡潔為主,更注重的其實是在質感方面。在同價位的車型中,想要找到一款內飾質感比得上捷達的並不容易。

後備廂容積:442L

其實外觀造型更飽滿了,都是為了實現更大的空間表現,現款捷達的空間表現也算得上是同級的上游水平。176cm的試乘員坐在前排,調整到舒適坐姿,頭部還剩1拳空間,保持前排坐姿,同一位試乘員坐到後排,頭部還剩4指空間,腿部空間更是大於兩拳。這樣的空間表現你真的確定是一款十萬不到就落地的合資德系車嗎?

發動機:1.4L/1.4T/1.5L

最大馬力(ps):90/110/131

最大扭矩(Nm):132/150/225

變速箱:5MT/6AT/7DCT

驅動方式:前置前驅

底盤懸挂:前麥弗遜獨立懸挂/后複合扭力梁式非獨立懸挂

動力匹配方面,現款捷達還挺多選擇的,但是1.4T的車型基本不推薦,因為太貴了。如果日常代步的話,其實1.4L的動力就夠了,只不過1.4L車型沒有配備自動變速箱的,不過很多車主都表示,捷達的手動擋車型真的很好開。

從車主口碑中,比較直觀的是車主們對捷達的油耗都非常滿意,以及後期保養也比較便宜。不滿意的地方也沒有什麼硬傷,都是一些無傷大雅的小問題而已。綜合各方面表現,其實捷達的表現還是比較均衡的,是一款很實在的車型。

其實許多大眾的轎車都有不錯的優惠幅度,至於捷達的話,一款定價本來就不高的車,可以拿到2-3萬的優惠幅度真的非常不錯了,不過具體需要加裝什麼精品,或要求在店上牌等等情況就因店而異了。

在這個價位的緊湊級轎車中,基本也很難找到對捷達有威脅的對手了,銷量一直領先於競品車型。

相信有很多人都有這樣的消費習慣,就是買東西的時候不會追求什麼個性、面子或一些附加的價值,這些人往往會選擇一些最實際,最務實的產品,不用顧慮太多後期的問題,而捷達就是這些消費們最合適的選擇。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

不談情懷只談性價比,這台300萬的買菜車是真的強!

採用三電機和3。5L雙渦輪增壓發動機的配合,組成中置引擎四驅系統,最大輸出功率可以達到573匹馬力,3。5秒以內就能完成百公里加速,性能已經媲美現在的主流歐美超跑。而混合動力組成的四驅系統,也能夠獲得較強的彎道性能。

隨着國內的汽車消費水平不斷提高,超跑已經不是可望而不可褻玩的車型,而是變成了更多有實力人士的玩具。而在三百萬以下這個級別,假如你不喜歡Huracan Lp580-2的張揚,又不喜歡R8 V10的功利主義。Mclaren 570s又有點輕佻,保時捷則又顯得不夠入流,而你又對獨一無二更看重的話,你或許會選擇這一台車,Acura NSX。

對於本田來說,NSX這三個字可以說是精神圖騰一般的存在。初代的NSX以打敗法拉利當時的旗艦348為己任,加入了F1的科技,採用全鋁車身和全鋁懸挂,加上VTEC加持的C30A發動機。極高的彎道極限和易於駕駛的特點打開了現代高性能跑車的大門,成為一代經典。

而新一代的NSX,則是Acura現在最先進的混合動力跑車。採用三電機和3.5L雙渦輪增壓發動機的配合,組成中置引擎四驅系統,最大輸出功率可以達到573匹馬力,3.5秒以內就能完成百公里加速,性能已經媲美現在的主流歐美超跑。而混合動力組成的四驅系統,也能夠獲得較強的彎道性能。

另一方面,也繼承了初代NSX那種易於駕駛的特點,甚至還刻意使用一些小技巧來提升行駛品質和舒適性。加上全國每年只有3台配額的身份,足以成為跑車玩家爭相擁有的目標。

而這台NSX究竟開起來怎樣,它究竟能用什麼方法來再一次詮釋“New Sportscar experimental”的核心精神?就請關注這一期的視頻。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案

這台頂配30多萬的2.0T中型SUV竟有50萬的質感?

與之匹配的是通用集團最新的9AT變速箱,這台變速箱是通用的重磅產品,不僅擋位數十分多,而且在平順性和響應速度上都十分出色。在加速測試中昂科威的扭矩峰值偏晚的問題也一定程度上影響了加速成績,實測8。2秒的成績雖然算是不錯了,但是激烈駕駛時感覺發動機的出力還是有些晚,需要拉到較高轉速才有明顯動力爆發。

如果說別克在主流家用車區間的大殺器是別克英朗的話,那麼撐起別克品牌形象的就一定是昂科威了,目前別克昂科威的銷量穩居合資車型前列,月均一萬以上的銷量在中型SUV中十分難得。就拿今年2月的數據來看,除了昂科威之外,其它的中型SUV銷量過萬的並不多,我們熟悉的冠道、漢蘭達、銳界等車型均不足萬台。

究其原因,昂科威大氣的外觀、豪華的內飾以及別克車型向來拿手的舒適性應該就是昂科威熱銷的原因了,不過在試駕之後,筆者對於昂科威也有了更深的認識,堪稱登峰造極的舒適性以及出色的動力表現讓筆者也愛不釋手。

試駕車型:別克昂科威2018款 28T 四驅全能運動旗艦型

指導價:31.99萬

昂科威在外觀上大量使用了別克的家族元素,直瀑式格柵搭配較大且精緻的大燈,霸氣感和精緻感都比較充分,厚實的車頭也很有敦實感,符合大多數人對於美系車的期待;而且昂科威的2.0T車型還標配了19吋的大輪轂,氣勢一下子就出來了,看着很有檔次感。

內飾上昂科威大量使用了深色木紋飾板,貫穿中控台的一大片木紋飾板不僅顏色足夠典雅,而且造型也很獨特,與整車的內飾融合得比較好,擋把周圍也使用了大面積的木紋飾板,不過亮面木紋飾板的壞處就是容易出現划痕;除此之外,昂科威的中控台上還有一隻精緻的小時鐘,細節點綴很到位。總體來看昂科威的內飾走的依舊是美式豪華路線,用料設計都十分不錯。

從外觀上看,昂科威的做工表現出了非常高的水準,整車的縫隙控制很到位,車漆的均勻度也比較出色,而且漆面的厚度也比許多日系車型要厚了不少。

我們這款昂科威屬於頂配車型,因此內飾看上去十分豪華精緻,但是在大量的按鍵和塑料面板的拼接處理上昂科威做得也是一絲不苟,緊緻的拼接、精細的做工對得起30萬出頭的售價。

說實在的,相比較同級別的中型SUV來說,昂科威的空間並不算出色,後排910mm的頭部空間甚至還不如一些緊湊型SUV,而且在我們實測中昂科威的後排座墊寬度也僅僅1210mm,表現在中型SUV里屬於比較讓人失望的了。

同樣不算出色的還有後備箱,昂科威的後備箱在輪拱處寬度只有1040mm,常規進深820mm也不算出色,750mm的後備箱高度表現一般。

昂科威搭載了一台2.0升渦輪增壓發動機,這台發動機的最大功率為260馬力,最大扭矩達到了400牛米,輸出數據非常出色,不過最大扭矩區間為3000-4000rpm,因此在渦輪遲滯上讓人比較擔心。

與之匹配的是通用集團最新的9AT變速箱,這台變速箱是通用的重磅產品,不僅擋位數十分多,而且在平順性和響應速度上都十分出色。

在加速測試中昂科威的扭矩峰值偏晚的問題也一定程度上影響了加速成績,實測8.2秒的成績雖然算是不錯了,但是激烈駕駛時感覺發動機的出力還是有些晚,需要拉到較高轉速才有明顯動力爆發。

昂科威的操控性能在中型SUV中屬於不錯的了,車身不會感覺拖沓,轉向的指向也算精準,不過低速時轉向阻尼的變化有些突兀感,轉向的手感也不是很輕,在轉向的回正力度設定上昂科威也不夠線性,因此轉向的反饋感覺並不是太好;好在轉向回正力矩不會向某些自主車那麼突兀暴力,感覺這個轉向還是比較好用的。

由於昂科威的車重達到了1.8噸,加上車身較高,懸挂也是偏向舒適性的設定,因此在過彎併線時依然有一些拖泥帶水的感覺,車輛的側向擺動有些多,看得出昂科威的底盤懸挂設定就是奔着舒適性去的。

發動機與變速箱的匹配比較到位,這一套動力系統直接秒殺了通用自家的幾乎全部6AT產品,日常駕駛完全感受不到換擋動作,油門響應也比較靈敏,市區駕駛這套動力系統能讓你開得很爽快,不過當你想要地板油加速時,變速箱的將擋就會有些遲緩,發動機出力也比較慢,感覺並不是非常好。

昂科威的舒適性可謂登峰造極,懸挂的濾震非常到位,路面上大大小小的振動都可以被過濾得十分充分,即使是軋過減速帶這種大顛簸,昂科威也能從容化解,傳遞到車內的振動微乎其微,再加上較為寬大柔軟的座椅,昂科威的乘坐感受還真是不錯。

除此之外,昂科威的隔音確實非常厲害,各類噪音都抑製得很充分,行駛到120km/h時噪音僅僅67.7分貝,這個測試成績已經超越了同場測試的保時捷卡宴。

評測車型的指導價為31.99萬,其實有些偏高了,不過好在昂科威目前在大部分地區都有好幾萬的優惠幅度,如果終端價格在30萬內的話還算可以接受。

坦白來說,昂科威的尺寸在中型SUV中屬於偏小的,這也直接反映在它的車內空間上了;除此之外昂科威似乎再沒有太多槽點了,出色的舒適性,不錯的隔音以及大氣精緻的內外設計,再加上昂科威不錯的口碑,如果想要在30萬左右買一台舒適性出色的SUV的話,昂科威2.0T車型還是很值得推薦的。

本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※帶您來了解什麼是 USB CONNECTOR  ?

※自行創業缺乏曝光? 網頁設計幫您第一時間規劃公司的形象門面

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!

※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

※廣告預算用在刀口上,台北網頁設計公司幫您達到更多曝光效益

※教你寫出一流的銷售文案?

不到40萬就能買4.8秒破百的3廂車,車主卻各種不滿?

發動機:2。0T最大馬力(ps):290最大扭矩(N·m)380變速箱:7DCT驅動方式:前置四驅前/后懸架類型:麥弗遜式獨立懸架/多連桿獨立懸架動力無疑是這款車的核心賣點,4。8秒左右的實測百公里加速時間,對於40萬以下的車型來說,幾乎找不到對手了。

什麼車可以扮豬吃老虎?

或許日系粉們還會想起

EVO、STI那些日系性能車

但是這些車在中國已經極少了

雖然高爾夫R、福克斯RS還能買到

但似乎也沒那麼接地氣了

畢竟許多中國消費者買車講究面子

就算對於性能車

也希望能有個豪華品牌的車標

而且三廂車似乎更符合國人的審美

實際上也更實用

所以像奧迪S3這樣的車型

指導價不到40萬

優惠過後35萬左右

百公里加速4.8秒

還能日常上下班

還能開去市場買車

看看車主到底是什麼感受

長*寬*高:4474*1796*1392mm

軸距:2628mm

車型定位:緊湊型車

外觀方面,奧迪S3基於奧迪A3打造,絕大部分零部件都是共享的,整體外觀造型也是一樣的,只是在細節方面做了一些點綴,比如車身前後的“S3”標識、四齣排氣、銀色的外后視鏡等。而且在車漆方面,也可以選擇S3的專屬車漆“聖邦藍”,整體效果比起奧迪A3個性不少,而且也顯得更精緻了,但也不會太激進,看上去也只能算是一輛買菜車的外觀。

內飾的整體布局跟奧迪A3也基本保持一致,但內飾方面做的點綴比外觀更明顯,處處可見,方向盤、座椅、門踏板等都有“S3”的標識。

空間方面的方面,1.78米的試乘員坐在前排調到最低位置調整好坐姿,頭部還剩餘4指空間,保持前排座椅不變,同一位試乘員坐進後排,頭部空間剩下1指,腿部空間剩下1拳4指。整體表現中規中矩,對於一輛緊湊級的三廂車而言,勉強夠用吧。

發動機:2.0T

最大馬力(ps):290

最大扭矩(N·m)380

變速箱:7DCT

驅動方式:前置四驅

前/后懸架類型:麥弗遜式獨立懸架/多連桿獨立懸架

動力無疑是這款車的核心賣點,4.8秒左右的實測百公里加速時間,對於40萬以下的車型來說,幾乎找不到對手了。而很多車主在體現0-100km/h加速的時候都感到車子起步時,前輪會有小小打滑,隨後四驅系統激活變直接衝出去,什麼推背感應該也不用我多說了。

從車主口碑中可以看出,最滿意的方面幾乎都是外觀或動力,但不滿意的地方都因人而異,各種各樣,所以其實要將奧迪S3看作是一輛動力很強的家用車,在實用性方面還是有些不足的。

優惠幅度各地不同,具體以4S店報價為準。有些車主則說沒太大優惠,不過基本都會有,只是幅度不同而已,但也有車主表示能拿到10W+的優惠,聽起來似乎不那麼靠譜,不過還是值得到店認證,如果真的能30萬不到就買到,那真的賺翻了。

其實在這個價位,要找一輛跟奧迪S3這樣的動力水平,而且還是4門的三廂車,幾乎是沒有的,而且這樣的車型定位在中國也應該有不錯的市場潛力,如果真的可以拿到5W以上的終端優惠,那應該是非常值得的。本站聲明:網站內容來源於http://www.auto6s.com/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※網頁設計一頭霧水該從何著手呢? 台北網頁設計公司幫您輕鬆架站!

※網頁設計公司推薦不同的風格,搶佔消費者視覺第一線

※想知道購買電動車哪裡補助最多?台中電動車補助資訊懶人包彙整

※南投搬家公司費用,距離,噸數怎麼算?達人教你簡易估價知識!

※教你寫出一流的銷售文案?

※超省錢租車方案