曹工說Spring Boot源碼(29)– Spring 解決循環依賴為什麼使用三級緩存,而不是二級緩存_網頁設計公司_網頁設計公司

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

寫在前面的話

相關背景及資源:

曹工說Spring Boot源碼(1)– Bean Definition到底是什麼,附spring思維導圖分享

曹工說Spring Boot源碼(2)– Bean Definition到底是什麼,咱們對著接口,逐個方法講解

曹工說Spring Boot源碼(3)– 手動註冊Bean Definition不比遊戲好玩嗎,我們來試一下

曹工說Spring Boot源碼(4)– 我是怎麼自定義ApplicationContext,從json文件讀取bean definition的?

曹工說Spring Boot源碼(5)– 怎麼從properties文件讀取bean

曹工說Spring Boot源碼(6)– Spring怎麼從xml文件裡解析bean的

曹工說Spring Boot源碼(7)– Spring解析xml文件,到底從中得到了什麼(上)

曹工說Spring Boot源碼(8)– Spring解析xml文件,到底從中得到了什麼(util命名空間)

曹工說Spring Boot源碼(9)– Spring解析xml文件,到底從中得到了什麼(context命名空間上)

曹工說Spring Boot源碼(10)– Spring解析xml文件,到底從中得到了什麼(context:annotation-config 解析)

曹工說Spring Boot源碼(11)– context:component-scan,你真的會用嗎(這次來說說它的奇技淫巧)

曹工說Spring Boot源碼(12)– Spring解析xml文件,到底從中得到了什麼(context:component-scan完整解析)

曹工說Spring Boot源碼(13)– AspectJ的運行時織入(Load-Time-Weaving),基本內容是講清楚了(附源碼)

曹工說Spring Boot源碼(14)– AspectJ的Load-Time-Weaving的兩種實現方式細細講解,以及怎麼和Spring Instrumentation集成

曹工說Spring Boot源碼(15)– Spring從xml文件裡到底得到了什麼(context:load-time-weaver 完整解析)

曹工說Spring Boot源碼(16)– Spring從xml文件裡到底得到了什麼(aop:config完整解析【上】)

曹工說Spring Boot源碼(17)– Spring從xml文件裡到底得到了什麼(aop:config完整解析【中】)

曹工說Spring Boot源碼(18)– Spring AOP源碼分析三部曲,終於快講完了(aop:config完整解析【下】)

曹工說Spring Boot源碼(19)– Spring 帶給我們的工具利器,創建代理不用愁(ProxyFactory)

曹工說Spring Boot源碼(20)– 碼網恢恢,疏而不漏,如何記錄Spring RedisTemplate每次操作日誌

曹工說Spring Boot源碼(21)– 為了讓大家理解Spring Aop利器ProxyFactory,我已經拼了

曹工說Spring Boot源碼(22)– 你說我Spring Aop依賴AspectJ,我依賴它什麼了

曹工說Spring Boot源碼(23)– ASM又立功了,Spring原來是這麼遞歸獲取註解的元註解的

曹工說Spring Boot源碼(24)– Spring註解掃描的瑞士軍刀,asm技術實戰(上)

曹工說Spring Boot源碼(25)– Spring註解掃描的瑞士軍刀,ASM + Java Instrumentation,順便提提Jar包破解

曹工說Spring Boot源碼(26)– 學習字節碼也太難了,實在不能忍受了,寫了個小小的字節碼執行引擎

曹工說Spring Boot源碼(27)– Spring的component-scan,光是include-filter屬性的各種配置方式,就夠玩半天了

曹工說Spring Boot源碼(28)– Spring的component-scan機制,讓你自己來進行簡單實現,怎麼辦

工程代碼地址思維導圖地址

工程結構圖:

什麼是三級緩存

在獲取單例bean的時候,會進入以下方法:

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)
    
protected Object getSingleton(String beanName, boolean allowEarlyReference) {
                // 1
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
                                // 2
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
                                        // 3
					ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                                                // 4
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return singletonObject;
	}

這裏面涉及到了該類中的三個field。

	/** 1級緩存 Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 2級緩存 Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

	/** 3級緩存 Cache of singleton factories: bean name to ObjectFactory. */
	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);

接著說前面的代碼。

  • 1處,在最上層的緩存singletonObjects中,獲取單例bean,這裏面拿到的bean,直接可以使用;如果沒取到,則進入2處

  • 2處,在2級緩存earlySingletonObjects中,查找bean;

  • 3處,如果在2級緩存中,還是沒找到,則在3級緩存中查找對應的工廠對象,利用拿到的工廠對象(工廠對像中,有3個field,一個是beanName,一個是RootBeanDefinition ,一個是已經創建好的,但還沒有註入屬性的bean),去獲取包裝後的bean,或者說,代理後的bean。

    什麼是已經創建好的,但沒有註入屬性的bean?

    比如一個bean,有10個字段,你new了之後,對像已經有了,內存空間已經開闢了,堆裡已經分配了該對象的空間了,只是此時的10個field還是null。

ioc容器,普通循環依賴,一級緩存夠用嗎

說實話,如果簡單寫寫的話,一級緩存都沒問題。給大家看一個我以前寫的渣渣ioc容器:

曹工說Tomcat4:利用Digester 手擼一個輕量的Spring IOC容器

@Data
public class BeanDefinitionRegistry {
    /**
     * map:存儲 bean的class-》bean實例
     */
    private Map<Class, Object> beanMapByClass = new ConcurrentHashMap<>();
    
    /**
     * 根據bean 定義獲取bean
     * 1、先查bean容器,查到則返回
     * 2、生成bean,放進容器(此時,依賴還沒注入,主要是解決循環依賴問題)
     * 3、注入依賴
     *
     * @param beanDefiniton
     * @return
     */
    private Object getBean(MyBeanDefiniton beanDefiniton) {
        Class<?> beanClazz = beanDefiniton.getBeanClazz();
        Object bean = beanMapByClass.get(beanClazz);
        if (bean != null) {
            return bean;
        }
		// 0
        bean = generateBeanInstance(beanClazz);


        // 1 先行暴露,解決循環依賴問題
        beanMapByClass.put(beanClazz, bean);
        beanMapByName.put(beanDefiniton.getBeanName(), bean);

        // 2 查找依賴
        List<Field> dependencysByField = beanDefiniton.getDependencysByField();
        if (dependencysByField == null) {
            return bean;
        }
		
        // 3
        for (Field field : dependencysByField) {
            try {
                autowireField(beanClazz, bean, field);
            } catch (Exception e) {
                throw new RuntimeException(beanClazz.getName() + " 創建失敗",e);
            }
        }

        return bean;
    }
}

大家看上面的代碼,我只定義了一個field,就是一個map,存放bean的class-》bean。

    /**
     * map:存儲 bean的class-》bean實例
     */
    private Map<Class, Object> beanMapByClass = new ConcurrentHashMap<>();
  • 0處,生成bean,直接就是new
  • 1處,先把這個不完整的bean,放進map
  • 2處,獲取需要注入的屬性集合
  • 3處,進行自動注入,就是根據field的Class,去map裡查找對應的bean,設置到field裡。

上面這個代碼,有啥問題沒?spring為啥整整三級?

ioc,一級緩存有什麼問題

一級緩存的問題在於,就1個map,裏面既有完整的已經ready的bean,也有不完整的,尚未設置field的bean。

如果這時候,有其他線程去這個map裡獲取bean來用怎麼辦?拿到的bean,不完整,怎麼辦呢?屬性都是null,直接空指針了。

所以,我們就要加一個map,這個map,用來存放那種不完整的bean。這裏,還是拿spring舉例。我們可以只用下面這兩層:

	/** 1級緩存 Cache of singleton objects: bean name to bean instance. */
	private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);

	/** 2級緩存 Cache of early singleton objects: bean name to bean instance. */
	private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);

因為spring代碼裡是三級緩存,所以我們對源碼做一點修改。

修改spring源碼,只使用二級緩存

修改創建bean的代碼,不放入第三級緩存,只放入第二級緩存

創建了bean之後,屬性注入之前,將創建出來的不完整bean,放到earlySingletonObjects

這個代碼,在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#doCreateBean,我這邊只有4.0版本的spring源碼工程,不過這套邏輯,算是spring核心邏輯,和5.x版本差別不大。

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
            // 1
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
		...
		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
            // 2
			earlySingletonObjects.put(beanName,bean);
			registeredSingletonObjects.add(beanName);
			// 3
//			addSingletonFactory(beanName, new ObjectFactory() {
//				public Object getObject() throws BeansException {
//					return getEarlyBeanReference(beanName, mbd, bean);
//				}
//			});
		}
  • 1處,就是創建對象,就是new
  • 2處,這是我加的代碼,放入二級緩存
  • 3處,本來這就是增加三級緩存的位置,被我註釋了。現在,就不會往三級緩存放東西了

修改獲取bean的代碼,只從第一、第二級緩存獲取,不從第三級獲取

org.springframework.beans.factory.support.DefaultSingletonBeanRegistry#getSingleton(java.lang.String, boolean)

之前的代碼是文章開頭那樣的,我這裏修改為:

	protected Object getSingleton(String beanName, boolean allowEarlyReference) {
		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				return singletonObject;
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);

這樣,就是只用兩級緩存了。

兩級緩存,有啥問題?

ioc循環依賴,一點問題都沒有,完全夠用了。

我這邊一個簡單的例子,


public class Chick{
    private Egg egg;

    public Egg getEgg() {
        return egg;
    }

    public void setEgg(Egg egg) {
        this.egg = egg;
    }
}

public class Egg {
    private Chick chick;

    public Chick getChick() {
        return chick;
    }

    public void setChick(Chick chick) {
        this.chick = chick;
    }
    <bean id="chick" class="foo.Chick" lazy-init="true">
        <property name="egg" ref="egg"/>
    </bean>
    <bean id="egg" class="foo.Egg" lazy-init="true">
        <property name="chick" ref="chick"/>
    </bean>
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext(
                "context-namespace-test-aop.xml");

        Egg egg = (Egg) ctx.getBean(Egg.class);

結論:

所以,一級緩存都能解決的問題,二級當然更沒問題。

但是,如果我這裏給上面的Egg類,加個切面(aop的邏輯,意思就是最終會生成Egg的一個動態代理對象),那還有問題沒?

    <aop:config>
        <aop:pointcut id="mypointcut" expression="execution(public * foo.Egg.*(..))"/>
        <aop:aspect id="myAspect" ref="performenceAspect">
            <aop:after method="afterIncubate" pointcut-ref="mypointcut"/>
        </aop:aspect>
    </aop:config>

注意這裏的切點:

execution(public * foo.Egg.*(..))

就是切Egg類的方法。

加了這個邏輯後,我們繼續運行,在 Egg egg = (Egg) ctx.getBean(Egg.class);行,會拋出如下異常:

我塗掉了一部分,因為那是官方對這個異常的推論,因為我們改了代碼,所以推論不準確,因此乾脆隱去。

這個異常是說:

兄弟啊,bean egg已經被注入到了其他bean:chick中。(因為我們循環依賴了),但是,注入到chick中的,是Egg類型。但是,我們這裏最後對egg這個bean,進行了後置處理,生成了代理對象。那其他bean裡,用原始的bean,是不是不太對啊?

所以,spring給我們拋錯了。

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

怎麼理解呢?以io流舉例,我們一開始都是用的原始字節流,然後給別人用的也是字節流,但是,最後,我感覺不方便,我自己悄悄弄了個緩存字符流(類比代理對象) ,我是方便了,但是,別人用的,還是原始的字節流啊。

你bean不是單例嗎?不能這麼玩吧?

所以,這就是二級緩存,不能解決的問題。

什麼問題?aop情形下,注入到其他bean的,不是最終的代理對象。

三級緩存,怎麼解決這個問題

要解決這個問題,必須在其他bean(chick),來查找我們(以上面例子為例,我們是egg)的時候,查找到最終形態的egg,即代理後的egg。

怎麼做到這點呢?

加個三級緩存,裏面不存具體的bean,裏面存一個工廠對象。通過工廠對象,是可以拿到最終形態的代理後的egg。

ok,我們將前面修改的代碼還原:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		BeanWrapper instanceWrapper = null;
		if (mbd.isSingleton()) {
			instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
		}
		if (instanceWrapper == null) {
            // 1
			instanceWrapper = createBeanInstance(beanName, mbd, args);
		}
		final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
		Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);

		boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
				isSingletonCurrentlyInCreation(beanName));
		if (earlySingletonExposure) {
            // 2
//			Map<String, Object> earlySingletonObjects = this.getEarlySingletonObjects();
//			earlySingletonObjects.put(beanName,bean);
//
//			Set<String> registeredSingletonObjects = this.getRegisteredSingletonObjects();
//			registeredSingletonObjects.add(beanName);
			
            // 3
			addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}
  • 1處,創建bean,單純new,不注入

  • 2處,revert我們的代碼

  • 3處,這裏new了一個ObjectFactory,然後會存入到如下的第三級緩存。

    	/** 3級緩存 Cache of singleton factories: bean name to ObjectFactory. */
    	private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
    

    注意,new一個匿名內部類(假設這個匿名類叫AA)的對象,其中用到的外部類的變量,都會在AA中隱式生成對應的field。

    大家看上圖,裏面的3個字段,和下面代碼1處中的,幾個字段,是一一對應的。

    			addSingletonFactory(beanName, new ObjectFactory() {
    				public Object getObject() throws BeansException {
                        // 1
    					return getEarlyBeanReference(beanName, mbd, bean);
    				}
    			});
    

ok,現在,egg已經把自己存進去了,存在了第三級緩存,1級和2級都沒有,那後續chick在使用getSingleton查找egg的時候,就會進入下面的邏輯了(就是文章開頭的那段代碼,下面已經把我們的修改還原了):

protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//		Object singletonObject = this.singletonObjects.get(beanName);
//		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
//			synchronized (this.singletonObjects) {
//				singletonObject = this.earlySingletonObjects.get(beanName);
//				return singletonObject;
//			}
//		}
//		return (singletonObject != NULL_OBJECT ? singletonObject : null);

		Object singletonObject = this.singletonObjects.get(beanName);
		if (singletonObject == null && isSingletonCurrentlyInCreation(beanName)) {
			synchronized (this.singletonObjects) {
				singletonObject = this.earlySingletonObjects.get(beanName);
				if (singletonObject == null && allowEarlyReference) {
					ObjectFactory singletonFactory = this.singletonFactories.get(beanName);
					if (singletonFactory != null) {
                        // 1
						singletonObject = singletonFactory.getObject();
						this.earlySingletonObjects.put(beanName, singletonObject);
						this.singletonFactories.remove(beanName);
					}
				}
			}
		}
		return (singletonObject != NULL_OBJECT ? singletonObject : null);
	}

上面就會進入1處,調用singletonFactory.getObject();

而前面我們知道,這個factory的邏輯是:

			addSingletonFactory(beanName, new ObjectFactory() {
				public Object getObject() throws BeansException {
                    // 1
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});

1處就是這個工廠方法的邏輯,這裏面,簡單說,就會去調用各個beanPostProcessor的getEarlyBeanReference方法。

其中,主要就是aop的主力beanPostProcessor,AbstractAutoProxyCreator#getEarlyBeanReference

其實現如下:

	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		this.earlyProxyReferences.add(cacheKey);
        // 1
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

這裏的1處,就會去對egg這個bean,創建代理,此時,返回的對象,就是個代理對象了,那,注入到chick的,自然也是代理後的egg了。

關於SmartInstantiationAwareBeanPostProcessor

我們上面說的那個getEarlyBeanReference就在這個接口中。

這個接口繼承了BeanPostProcessor

而創建代理對象,目前就是在如下兩個方法中去創建:

public interface BeanPostProcessor {
    Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
    
	Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;    
}

這兩個方法,都是在實例化之後,創建代理。那我們前面創建代理,是在依賴解析過程中:

public interface SmartInstantiationAwareBeanPostProcessor extends InstantiationAwareBeanPostProcessor {
    ...
	Object getEarlyBeanReference(Object bean, String beanName) throws BeansException;
}

所以,spring希望我們,在這幾處,要返回同樣的對象,即:既然你這幾處都要返回代理對象,那就不能返回不一樣的代理對象。

那我們再看看,到底,AbstractAutoProxyCreator有沒有遵守約定呢,這幾個方法裡,有沒有去返回同樣的代理包裝對象呢?

getEarlyBeanReference

	public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
        // 1
		this.earlyProxyReferences.add(cacheKey);
		return wrapIfNecessary(bean, beanName, cacheKey);
	}

1處,往field:

private final Set<Object> earlyProxyReferences =
      Collections.newSetFromMap(new ConcurrentHashMap<Object, Boolean>(16));

裡,加了個cachekey,這個cachekey,主要也就是如下的字符串,用來唯一標識而已。

	protected Object getCacheKey(Class<?> beanClass, String beanName) {
		return beanClass.getName() + "_" + beanName;
	}

我們可以看看這個field在哪裡被用到了。

也就兩處,一處就是當前位置;另外一處,下面講。

這裏,主要就是看看到底要不要生成代理對象,要的話,就生成,不要就算了,另外,做了個標記:在earlyProxyReferences加了當前bean的key,表示:當前bean,已經被getEarlyBeanReference方法處理過了。

至於,最終到底有沒有生成代理對象,另說。畢竟調用wrapIfNecessary也不是說,一定就滿足切面,要生成代理對象。

可能返回的仍然是原始對象。

postProcessBeforeInitialization

public Object postProcessBeforeInitialization(Object bean, String beanName) {
   return bean;
}

這一處,沒做處理。

postProcessAfterInitialization

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
            // 1
			if (!this.earlyProxyReferences.contains(cacheKey)) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

這裏,1處這個判斷哈,就用到了前面我們說的那個field。那個field,只在兩處用,一處就是調用getEarlyBeanReference,會往裡面把當前bean的key放進去;另外一處,就是這裏。

這裏判斷,如果field裡不包含當前bean,就去調用wrapIfNecessary;如果包含(意味著,getEarlyBeanReference處理過了),就不調用了。

這裏,說到底,就是保證了,wrapIfNecessary只被調用一次。

看吧,wrapIfNecessary也就這兩處被調用了。

所以,我們可以得出結論,在aop這個beanPostProcessor中,有多處機會可以返回一個proxy對象,但是,最終,只要在其中一處處理了,其他處,根本不再繼續處理。

另外,還有一點很重要,在這個aop beanPostProcessor中,傳入了原始的bean,我們會去判斷,是否要給它創建代理,如果要,就創建;如果不要則:

返回原始對象

整個流程串起來

上面這個後置處理器看明白了,接下來,再看看創建bean的核心流程:

protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
		// 1 
		BeanWrapper instanceWrapper = createBeanInstance(beanName, mbd, args);
		final Object bean = instanceWrapper.getWrappedInstance();
		
		if (earlySingletonExposure) {
            // 2
			addSingletonFactory(beanName, new ObjectFactory() {
				@Override
				public Object getObject() throws BeansException {
					return getEarlyBeanReference(beanName, mbd, bean);
				}
			});
		}

		// 3 
		Object exposedObject = bean;
    	// 4
        populateBean(beanName, mbd, instanceWrapper);
		
    	// 5
        if (exposedObject != null) {
            exposedObject = initializeBean(beanName, exposedObject, mbd);
        }

		if (earlySingletonExposure) {
            // 6
			Object earlySingletonReference = getSingleton(beanName, false);
            
			if (earlySingletonReference != null) {
                // 7
				if (exposedObject == bean) {
					exposedObject = earlySingletonReference;
				}
				else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
                    // 8
                    ...
				}
			}
		}

		return exposedObject;
	}

上面流程中,做了部分刪減。但基本創建一個bean,就這幾步了。

  • 1處,創建bean對象,此時,屬性什麼的全是null,可以理解為,只是new了,field還沒設置

  • 2處,添加到第三級緩存;加進去的,只是個factory,只有循環依賴的時候,才會發揮作用

  • 3處,把原始bean,存到exposedObject

  • 4處,填充屬性;循環依賴情況下,A/B循環依賴。假設當前為A,那麼此時填充A的屬性的時候,會去:

    new B;

    填充B的field,發現field裡有一個是A類型,然後就去getBean(“A”),然後走到第三級緩存,拿到了A的ObjectFactory,然後調用ObjectFactory,然後調用AOP的後置處理器類:getEarlyBeanReference,拿到代理後的bean(假設此處切面滿足,要創建代理);

    經過上面的步驟後,B裏面,field已經填充ok,其中,且填充的field是代理後的A,這裏命名為proxy A。

    B 繼續其他的後續處理。

    B處理完成後,被填充到當前的origin A(原始A)的field中

  • 5處,對A進行後置處理,此時調用aop後置處理器的,postProcessAfterInitialization;前面我們說了,此時不會再去調用wrapIfNecessary,所以這裏直接返回原始A,即origin A

  • 6處,去緩存裡獲取A,拿到的A,是proxy A

  • 7處,我們梳理下:

    exposedObject:origin A

    bean:原始A

    earlySingletonReference: proxy A

    此時,下面這個條件是滿足的,所以,exposedObject,最終被替換為proxy A:

    if (exposedObject == bean) {
        exposedObject = earlySingletonReference;
    }
    

源碼

文章用到的aop循環依賴的demo,自己寫一個也可以,很簡單:

https://gitee.com/ckl111/spring-boot-first-version-learn/tree/master/all-demo-in-spring-learning/spring-aop-xml-demo-cycle-reference

不錯的參考資料

https://blog.csdn.net/f641385712/article/details/92801300

總結

如果有問題,歡迎指出;歡迎加群討論;有幫助的話,請點個贊吧,謝謝

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

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

三星S21系列預購活動懶人包_網頁設計公司

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

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

三星5G新一代旗艦機Galaxy  S20、 S21+、S21 Ultra正式宣將在 1 月 29 日上市,並將於 1 月 15 日 15:30 起舉辦預購活動,並推出一系列預購禮與排隊禮。因應iPhone 12系列採取平價策略,這次三星S21系列,相較前一代S20系列,不但增加了一些新功能(如S21 Ultra多了可選購SPEN),建議售價還少了4000元以上,可以看出三星的企圖心!

三星S21系列的功能規格差異為何呢? 有哪些預購活動呢? 以下作一整理:

掌握最新電信資費訊息,請加入小丰子3C俱樂部粉絲頁!

小丰子3C俱樂部

 

1.S21系列建議售價與規格:

台灣三星1/29將在台上市5G新一代旗艦機Galaxy  S20、 S21+、S21 Ultra,其中S21 Ultra 首次加入S-Pen功能。 5G版本的 Galaxy S21系列的在台售價比較如下:

 

以下是三星S20、 S21+、S21 Ultra功能與規格比較:

 

2.預購活動:

A.Galaxy S21 5G 旗艦系列預購方案:

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

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

預購時間:1 月 15 日 15:30 至 1 月 25 日 23:59 期間開放預購登記。

預購好禮:
a.預購 Galaxy S21 Ultra 5G 並上網登錄送:Galaxy Buds Pro 真無線藍牙耳機(建議售價 NT$6,990)、Galaxy SmartTag 藍牙智慧防丟器(建議售價 NT$990)。
b.預購 Galaxy S21+ 5G︱Galaxy S21 5G 並上網登錄送:Galaxy Buds Live 真無線藍牙耳機(建議售價 NT$5,990)、Galaxy SmartTag 藍牙智慧防丟器(建議售價 NT$990)。

 

B.三星智慧館/三星商城預購方案:

a.預購取貨-限量線上排隊禮:
活動時間:1 月 15 日至 1 月 25 日止。
活動內容:於全台三星智慧館 Galaxy S21 5G 旗艦系列預購排隊網站登記,並於 1 月 27 日至 2 月 7 日憑預購 序號完成預購取機,即可獲得線上排隊禮郵政禮券 NT$1,000,限量 4,000 份。
指定店家優先取機排隊:三星微風南山旗艦體驗館限定取機加碼,於 1 月 27 日至 1 月 29 日至活動網頁預約,取機再送郵政禮券 NT$1,000,限量 350 份。

b.Samsung Care+全新上市三星智慧館獨家享悠遊卡加值回饋 NT$700:
活動時間:1 月 27 日至 3 月 31 日止。
活動內容:於全台三星智慧館購買 Galaxy S21 5G 旗艦系列手機,加購 Samsung Care+並繳滿六期保費,即可獲贈 Samsung Pay 悠遊卡加值回饋 NT$700。

 

C.Galaxy S21 5G 旗艦系列非預購方案:
非預購之消費者自 1 月 29 日起至 3 月 31 日期間,於全通路購買 Galaxy S21 5G 旗艦級系列手機並上網登錄,即可獲得【三合一無線閃充充電板(建議售價 NT$2,990)】、【Galaxy SmartTag 藍牙智慧防丟器(建議售價 NT$990)】; 購買 Galaxy S21 Ultra 5G 加贈【矽膠薄型背蓋(附 S Pen)(建議售價 NT$1,990)】。凡購買 Galaxy S21 5G 旗艦系列,可享 YouTube Premium 免費試用 4 個月。

 

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

國外 YouTube 頻道實測 PS5 vs 電腦 120FPS 模式的遊戲效能表現,GTX 1060 就贏過 PS5_網頁設計公司

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

PlayStation 5 顯示效能非常強大,這點相信很多人都知道,Sony 也曾透露最高能支援到 120FPS,這數字可說相當吸引遊戲玩家,而先前也有外媒實測確實有一些 PS5 遊戲可跑到 120FPS。為此近日就有國外 YouTube 頻道想到一個還蠻有趣的比較主題,如果以相同約 500 美金的電腦跟 PS5 相比,一樣的遊戲運行 120FPS,哪些顯示卡可以跟 PS5 表現一樣?結果沒想到四年前的 NVIDIA GTX 1060 就能擊敗 PS5。

國外 YouTuber 實測 PS5 vs 電腦 120FPS 模式的遊戲效能表現

開始介紹前也先說明一下,這位 YouTuber 的 PS5 vs PC 比較是以 120FPS 為前提,因此並不代表 PS5 效能這麼差,畢竟 PS5 都能運行 4K 遊戲,甚至未來還能支援到 8K,再加上 5.5 GB/s 客製化 NVME SSD,很多地方是這次測試表現不出來。

以下是先前外媒 PushSquare 分享 PS5 可運行 120FPS 的遊戲清單:

  • Borderlands 3 (PS5)
  • Call of Duty: Black Ops Cold War (PS5)
  • Destiny 2 (PS5)
  • Devil May Cry 5: Special Edition (PS5)
  • DIRT 5 (PS5)
  • Monster Boy and the Cursed Kingdom (PS5)
  • The Nioh Collection (PS5)
  • Tom Clancy’s Rainbow Six: Siege (PS5)

Gamers Nexus 就拿 Borderlands 3、Devil May Cry 5: Special Edition 與 DIRT 5 這三款遊戲進行測試。而畫質部分都是運行 1080p,品質設定基本上一模一樣,甚至把 PS5 的光追技術關掉。

首先是 Devil May Cry 5: Special Edition,這款遊戲幾乎不需要使用到 CPU 的效能,因此他們選擇 R3 3300X 就夠了,甚至還可以再往更低階挑,不過以 400~500 美金為前提,這顆跟 PS5 最接近。

下方是 PC 端的畫質設定:

顯示卡部分他們測試過 GTX 1070,會比 PS5 還要好,也因此降一級改用 GTX 1060 就差不多,測試時把光追關掉:

跑分結果,PC 部分平均可跑到 142.1 FPS,但 PS5 只能到 108.7 FPS:

DIRT 5 這款遊戲顯卡要用到 GTX 1080 才比較接近 PS5,不過以平均 FPS 來說,PS5 就以 119FPS 小勝 PC 的 108.9FPS:

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

PS5 與 PC 同一畫面的比較圖:

最後是 Borderlands 3,這款遊戲需要用到 GTX 1070 Ti 才跟 PS5 最接近,PC 以平均 130.3FPS 表現勝過 PS5 的 118.9FPS:

同一畫面比較圖:

有些人可能會覺得,測試這似乎沒什麼意義,事實上還是有一個可以總結的答案,就是以高 FPS 的畫面表現來說,遊戲機表現不會比 PC 還出色,因此如果你是看中這一點想買 PS5 的人,PC 會是你更好的選擇。

說實在 PS5 vs PC 本來就很難相提並論,畢竟 PC 還能做很多事情,像是文書、繪圖等等,非常多功能,而 PS5 則可以讓玩家無需擔心遊戲不順暢狀況,進而提供最佳體驗。

完整影片:

IKEA 開始提供 PS5 與 Xbox Series X 的紙模型,讓你買家具之前可以快速比對

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

Apple 正在阻止 M1 Mac 設備用戶從非 APP Store 安裝應用程式_網頁設計公司

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

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

自從 Apple 推出 M1 晶片與配備該晶片的 Mac 設備,優異的效能與飛快的速度讓人印象深刻,可支援 iOS 應用程式的功能也讓人們開始試著在設備上安裝各種應用。現在 Apple 開始關閉用戶在 M1 Mac 上安裝並非來自 APP Store 的應用程式,像是許多人愛用的影音串流平台 Netflix 等。

Apple 正在阻止 M1 Mac 設備用戶從非 APP Store 安裝應用程式

M1 的特性就是能夠讓用戶在 Mac 設備上安裝 iOS 應用程式,雖說部分應用的開發者可能因為怕影響使用體驗等原因,當初的設定是不允許用戶在 Mac 上運行,但用戶還是可以利用 iMazing 等工具軟體來安裝使用原本無法支援的應用程式,包含 Netflix、Facebook、Instagram 等,不過接下來,這繞過機制的招式也將行不通了。

國外媒體 9to5Mac 現在已經證實,除非應用程式本身在 Mac 的 APP Store 終究開放下載使用,否則現在 Apple 已經將伺服器上的通道關掉,以阻止用戶繼續在 M1 Mac 上安裝。此更改將適用於運行 macOS Big Sur 11.1 的 M1 Mac 、macOS Big Sur 11.2 測試版與開發者版本,唯一的區別在於後者可以看到更具體的視窗通知內容(如下圖)。

長期以來 Mac 用戶已經習慣在 Mac 系統上擁有比 iOS 更高的自由度,儘管 Apple 多年來一直在收緊管理。規則的改變是從 APP Store 系統中進行,而該系統提供 Apple 管理作業系統DRM (數位版權管理)保護 API 一部分的 IPA 檔,因此未來不太可能會有解決方案出現,除非哪天 Apple 想開,或是原本鎖定的那些應用程式自行開放相容。

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

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

◎資料來源:The Verge、9to5Mac

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

伊朗核設施發生四次神秘爆炸後 致信歐盟_網頁設計公司

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

摘錄自2020年7月6日大紀元報導

在與導彈和核項目相關的重要基礎設施近日連續發生神秘爆炸之後,伊朗致信歐盟。歐盟外交政策負責人約瑟夫・博雷爾(Josep Borrell)表示,伊朗當局以英、法、德政府未能很好地支持伊朗核協議的執行為由,啟動了伊朗核協議中的爭端解決機制。

美國川普總統於2018年5月8日退出了由美、英、德、法、中、俄於2015年聯合簽署的伊朗核協議,理由是此核協議並未制裁伊朗的彈道導彈項目, 伊朗隨後以拒絕執行核協議中的關鍵條款為由,要挾國際社會對美國政府施壓, 並於2020年1月5日宣布伊朗暫停履行伊朗核協議,並對該國持有的離心機數量不再進行限制。英、法、德三國政府因此於1月14日宣布, 根據伊朗核協議,啟動協議的爭端解決機制,以期重返伊朗核協議框架。伊朗則揚言要退出次協議及《全球核不擴散條約》, 但是後來未採取相關舉措。

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

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

聯合國國際原子能機構6月19日通過決議案,要求伊朗允許該機構的國際調查員進入該國的兩個被控曾存放未申報的核原料的設施裡進行檢查。這令伊朗惱怒,扎里夫隨後在其推特上譴責英、法、德未能脅迫美國停止對其制裁。

從6月26日起,伊朗導彈和核項目相關的重要基礎設施已經發生了4次原因不明的爆炸或火災現象。這不禁讓人質疑伊朗對國際社會承諾的其核武項目的安全性,這些火災事故表明伊朗在國防和基礎設施的維護上面是失敗的。

能源轉型
國際新聞
伊朗
核能

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

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

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

美科學家研發可降溫的白漆 減少冷氣使用_網頁設計公司

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

摘錄自2020年11月9日大紀元報導

美國科學家研發出一種可降低建築物表面溫度的白漆,而且不用插電,這有助於減少冷氣與能源的消耗。

據美國普渡大學網站報導,該校研究人員開發出一種白漆,可使物體的表面溫度比周遭環境低華氏18度(攝氏7.8度),這幾乎就像冰箱的功能,但卻不需要消耗電力。

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

研究人員指出,有別於一般油漆會吸收陽光的能量,這種白漆幾乎不會吸收陽光的能量,而是將熱量驅離建築物,使其溫度不至於升高。在這種情況下,人們就無須使用冷氣。

該校機械工程系的一段短片顯示,這種白漆不光是將熱量從表面排出,還會將它以光速輻射到太空中。如此,熱量不會困在大氣層中,以至於增加溫室效應。它能減少汽車、建築物和工廠的能源消耗。

氣候變遷
國際新聞
美國
氣候暖化
減碳降溫

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

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

微型塑膠污染:大西洋上的塑膠廢料總重「或達2100萬噸」_網頁設計公司

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

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。

摘錄自2020年8月19日BBC報導

科學家發現,目前在大西洋上漂浮的微型塑膠碎片共計重1200至2100萬噸。

由英國國家海洋學中心領頭的一個項目,在大西洋中部進行考察研究,探索了海面至200米深的區域。得出的發現是,2100萬噸這個量級的塑膠,可以完全裝滿近1000艘集裝箱船。該發現已經刊登在期刊《自然通訊》(Nature Communications)上。

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

英國國家海洋學中心領導此次研究的卡茨亞.帕波爾茨亞娃博士(Katsia Pabortsava)表示,通過測量海洋最表層5%範圍深度內的極小型塑膠碎片,她和同事們估算,「整個大西洋的塑膠量」比此次估計的數字要「大得多」。

在新型冠狀病毒全球大流行疫情期間,一些環境保護組織已經報告,可丟棄的口罩現在成為最常見的塑膠丟棄品之一。

海洋
國際新聞
海廢
微塑膠
塑膠微粒
海洋垃圾

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

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

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

「耳朵大大、眼睛圓圓」米老鼠!澳發現2「大型有袋類」新物種_網頁設計公司

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

當全世界的人們隨著網路時代而改變向上時您還停留在『網站美醜不重要』的舊有思維嗎?機會是留給努力改變現況的人們,別再浪費一分一秒可以接觸商機的寶貴時間!

摘錄自2020年11月12日太報報導

澳洲生物學家意外發現大型滑翔有袋動物(Greater glider)「大袋鼯」並非單一物種,至少已有兩個新物種獲得命名。

生物學家過往發現當地大型滑翔有袋動物,例如大袋鼯,實際上有著不一樣的身形、顏色和生理差異。因此,生物學家合理懷疑牠們不是單一物種,卻苦無證據證明。

直到最近,生物學家針對大袋鼯屬(Petauroides volans)進行多樣性陣列(DArT)測序,發現牠們實際上還有兩個同屬不同種的物種,學名分別被命名為「Petauroides minor」及「Petauroides armillatus」。

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

透過資料庫的網站架設建置,建立公司的形象或購物系統,並提供最人性化的使用介面,讓使用者能即時接收到相關的資訊

雖然,牠們與大袋鼯同屬不同種、擁有不一樣的外表體徵,但牠們一樣只吃桉樹葉,生活於大分嶺(Great divide Range)沿線森林內。

近幾十年來,澳洲環境面臨人類的濫墾濫伐、森林大火、氣候暖化等挑戰。因此,野生動物生態學系揚托布博士(Dr. Kara Youngentob)期待生物學家能盡快展開研究,表示:「我們對這兩物種一無所知,若不開始研究,未來恐怕會失去牠們。」

生物多樣性
國際新聞
澳洲
有袋類動物

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

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

RWD(響應式網頁設計)是透過瀏覽器的解析度來判斷要給使用者看到的樣貌

因應疫情危機 英國石油公司傳將裁員15%_網頁設計公司

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

節能減碳愛地球是景泰電動車的理念,是創立景泰電動車行的初衷,滿意態度更是服務客戶的最高品質,我們的成長來自於你的推薦。

摘錄自2020年6月8日中央社報導

英國石油公司(BP)消息人士今天告訴路透社,英國石油公司計畫裁員約15%,以因應武漢肺炎(COVID-19)疫情危機。

路透社報導,這些消息人士指稱,英國石油公司執行長盧尼(Bernard Looney)並計畫讓公司轉型,從以石油和天然氣業務為主改成以再生能源為主,這次裁員是計畫中的一部分。

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

搬家費用:依消費者運送距離、搬運樓層、有無電梯、步行距離、特殊地形、超重物品等計價因素後,評估每車次單

他們透露,盧尼在全球線上會議告訴員工,英國石油公司將從現今7萬100名員工中裁減1萬人,其中多數將在年底前遭到裁員。今年4月,英國石油公司才宣布削減今年25%的預算支出,因為疫情導致石油需求出現前所未見下滑。

生活環境
國際新聞
英國
武漢肺炎
疫情
石油公司
裁員
疫情看氣候與能源

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

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

透過選單樣式的調整、圖片的縮放比例、文字的放大及段落的排版對應來給使用者最佳的瀏覽體驗,所以不用擔心有手機版網站兩個後台的問題,而視覺效果也是透過我們前端設計師優秀的空間比例設計,不會因為畫面變大變小而影響到整體視覺的美感。

聯發科最新旗艦級 5G 系統單晶片天璣1200 發表,以頂級效能、AI 影像與高品質 5G 連線為主打_網頁設計公司

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

網站的第一印象網頁設計,決定了客戶是否繼續瀏覽的意願。台北網動廣告製作的RWD網頁設計,採用精簡與質感的CSS語法,提升企業的專業形象與簡約舒適的瀏覽體驗,讓瀏覽者第一眼就愛上它。

聯發科今日(1/20)以線上發表的方式公布了自家最新一代旗艦級 5G 系統單晶片天璣 1200 與 1100,皆採台積電 5nm 製程,標榜在 5GAI、拍照、影片、遊戲等全方面帶來頂級表現,滿足消費者超快速無線連結體驗,為快速增長的5G全球行動市場注入新動力,終端產品將於今年度陸續問市。

聯發科最新旗艦級 5G 系統單晶片天璣1200 發表,以頂級效能、AI 影像與高品質 5G 連線為主打

天璣 1200 整合聯發科 5G 數據機,測試並通過德國萊因 (TÜV Rheinland) 認證,在 6 大維度、72 個應用場景支援高效 5G 連線,帶給使用者全方位的高品質 5G 體驗。邁入 5G 時代,AI 多媒體成為主流應用,天璣 1200 以強勁的平台效能為基礎,結合自家 AI 多媒體技術,例如三重曝光的單幀逐行 Staggered 4K HDR 影像技術,為使用者帶來更豐富的拍照、影像、直播等多媒體創作方式,以及更精緻的行動視覺享受。

天璣 1200 採用台積電 6 奈米製程,CPU 以 1 + 3 + 4 的旗艦級三叢架構設計,包含 1 個主頻達 3.0GHz 的 Arm Cortex-A78 大核,搭配九核 GPU 和六核聯發科 APU 3.0,以及雙通道 UFS 3.1,一舉大幅提升。所採用的獨立 AI 處理器 APU 3.0,可充分發揮混合精度優勢,靈活運用整數精度與浮點數精度運算,達到更高的 AI 能效;結合 AI 多工調度機制,通過 AI 降噪、AI 曝光、AI 物體追蹤等技術的高度融合,為使用者帶來「疾速夜拍」和「超級全景夜拍」等拍照新體驗。

支援晶片級單幀逐行 Staggered 4K HDR 影像技術,在使用者錄製 4K 影片時,對每格畫面進行 3 次曝光融合處理,讓影片畫質增加 40% 動態範圍,顯著提升色彩、對比度、及細節。同時,結合 HDR10+ 影像編碼技術,完整輸出 Staggered HDR 影音效果,處理過程中影像不經過壓縮還原,保留最佳品質,並可適用於電視、手機、平板等不同終端裝置播放,為消費者帶來驚豔的 HDR 體驗。另外,天璣 1200 支援 AI 多人即時分割,讓使用者輕鬆打造多人背景替換、多路人移除等電影級拍攝特效,加上多景深智慧對焦、AI 串流媒體畫質增強等影像技術,讓 4K 影音創作有更多可能性。

在 5G 方面,可支援獨立 (SA) 和非獨立 (NSA) 組網模式、5G 雙載波聚合 (2CC CA)、動態頻譜共用 (DSS) 等,內建聯發科 5G UltraSave 省電技術,以及 5G SA/NSA 雙模組網下的雙卡 5G 待機、雙卡 VoNR 語音服務等。天璣 1200 不僅支持全球 5G 營運商的 Sub-6GHz 全頻段和大頻寬,還為使用者打造全景全時的 5G 無縫連線體驗,推出「5G 高鐵模式」、「5G 電梯模式」等應用,透過智慧場景感知、訊號的快速捕捉及追蹤、自動偵測並切換網路,讓終端裝置擁有高效且穩定的 5G 性能;結合聯發科 5G UltraSave省電技術,帶來更低功耗的 5G 通訊。

搭載了全新升級的 HyperEngine 3.0 遊戲引擎,再次升級遊戲網路體驗,在 5G 網路連線下可實現遊戲通話雙卡並行,使用者可以在主卡玩手遊的同時接聽副卡來電,遊戲持續不斷線。超級熱點和高鐵遊戲模式則針對不同的遊戲環境進行網路最佳化,有效降低遊戲網路延遲。對於遊戲玩家而言,HyperEngine 3.0 的操控引擎能讓多指操控時的觸控採樣率保持穩定的高幀數,且 HyperEngine 3.0 的智慧負載調控引擎新增遊戲高顯示更新率下省電功能、智慧健康充電、Wi-Fi 6 省電模式,用以平衡效能與功耗,延長續航和電池壽命。

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

台中景泰電動車行只是一個單純的理由,將來台灣的環境,出門可以自由放心的深呼吸,讓空氣回歸自然的乾淨,減少污染,留給我們下一代有好品質無空污的優質環境

聯發科 HyperEngine 佈局圖形關鍵技術光線追蹤(Ray Tracing),為遊戲廠商、開發者、終端提供強大的圖形處理能力,為手遊玩家帶來媲美真實的遊戲畫面,引領行動端圖形技術趨勢。另外,天璣 1200 支援即將發表的藍牙 LE Audio (Bluetooth Low Energy Audio,藍牙低功耗音訊)  標準,擴充至雙鏈路音訊串流,帶來比傳統 TWS 耳機更加穩定及高品質的音訊,並降低 20% 延遲及功耗,延長耳機的續航力。聯發科表示,在 2021 年會從技術端、產品端、品牌端持續創新、投入,持續在全球領域推動 5G 發展與創新,讓天璣系列為 5G 終端市場開創更多可能,為使用者帶來更卓越、更豐富的使用體驗。

 

您也許會喜歡:

【推爆】終身$0月租 打電話只要1元/分

立達合法徵信社-讓您安心的選擇

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

以設計的實用美學觀點,規劃出舒適、美觀的視覺畫面,有效提昇使用者的心理期待,營造出輕鬆、愉悅的網站瀏覽體驗。