Spring AOP源碼解析

1、AOP核心概念

1)、橫切關注點(對哪些方法進行切入)

對哪些方法進行攔截,攔截后怎么處理,這些關注點稱之為橫切關注點

2)、切面(aspect,把原來糅雜在業務邏輯代碼中的非業務代碼抽取出來,把功能相同的放在一個類中形成一個切面)

類是對物體特征的抽象,切面就是對橫切關注點的抽象

3)、連接點(joinpoint)(需要切入的點)

被攔截到的點,因為Spring只支持方法類型的連接點,所以在Spring中連接點指的就是被攔截到的方法,實際上連接點還可以是字段或者構造器

4)、切入點(pointcut)

對連接點進行攔截的定義

5)、通知(advice)

所謂通知指的就是指攔截到連接點之后要執行的代碼,通知分為前置、后置、異常、最終、環繞通知五類

6)、目標對象

代理的目標對象

7)、織入(weave)

將切面應用到目標對象并導致代理對象創建的過程

8)、引入(introduction)

在不修改代碼的前提下,引入可以在運行期為類動態地添加一些方法或字段

簡單案例:

public interface Calculate {

/**

* 加法

* @param numA

* @param numB

* @return

*/

int add(int numA,int numB);

/**

* 減法

* @param numA

* @param numB

* @return

*/

int reduce(int numA,int numB);

/**

* 除法

* @param numA

* @param numB

* @return

*/

int div(int numA,int numB);

/**

* 乘法

* @param numA

* @param numB

* @return

*/

int multi(int numA,int numB);

}

=====================實現類

public class CalculateImpl implements Calculate {

public int add(int numA, int numB) {

return numA+numB;

}

public int reduce(int numA, int numB) {

return numA-numB;

}

public int div(int numA, int numB) {

return numA/numB;

}

public int multi(int numA, int numB) {

return numA*numB;

}

}

=====================切面類=====================

@Aspect

public class LogAspect {

@Pointcut("execution(* com.jd.CalculateImpl.*(..))")

public void pointCut(){};

@Before(value = "pointCut()")

public void methodBefore(JoinPoint joinPoint){

String methodName = joinPoint.getSignature().getName();

System.out.println("執行目標方法【"+methodName+"】之前執行<前置通知>,入參"+ Arrays.asList(joinPoint.getArgs()));

}

@After(value = "pointCut()")

public void methodAfter(JoinPoint joinPoint) {

String methodName = joinPoint.getSignature().getName();

System.out.println("執行目標方法【"+methodName+"】之前執行<后置通知>,入參"+Arrays.asList(joinPoint.getArgs()));

}

@AfterReturning(value = "pointCut()")

public void methodReturning(JoinPoint joinPoint ) {

String methodName = joinPoint.getSignature().getName();

System.out.println("執行目標方法【"+methodName+"】之前執行<返回通知>,入參"+Arrays.asList(joinPoint.getArgs()));

}

@AfterThrowing(value = "pointCut()")

public void methodAfterThrowing(JoinPoint joinPoint) {

String methodName = joinPoint.getSignature().getName();

System.out.println("執行目標方法【"+methodName+"】之前執行<異常通知>,入參"+Arrays.asList(joinPoint.getArgs()));

}

}

===========================配置類=============

@Configuration

@EnableAspectJAutoProxy

public class MainConfig {

@Bean

public Calculate calculate() {

return new CalculateImpl();

}

@Bean

public LogAspect logAspect() {

return new LogAspect();

}

}


2)我們看到在我們配置類上加入了@EnableAspectJAutoProxy這個東東?我registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);

們著重來分析一下這個東東給我容器中添加了什么組件?

2.1)我們發現@EnableAspectJAutoProxy上標注了一個@Import注解,通過前面的學習我們知道

@Import可以給我們容器中添加組件

@Target(ElementType.TYPE)

@Retention(RetentionPolicy.RUNTIME)

@Documented

@Import(AspectJAutoProxyRegistrar.class)

public @interface EnableAspectJAutoProxy {

2.2)所有我們來分析AspectJAutoProxyRegistrar類是用來干什么的?

經過跟蹤源代碼我們發現,AspectJAutoProxyRegistrar實現了ImportBeanDefinitionRegistrar接口,我們以前學習過

凡是實現了ImportBeanDefinitionRegistrar可以給我們容器中添加bean定義信息

作用:往容器中注冊了一個名稱叫org.springframework.aop.config.internalAutoProxyCreator

類型為AnnotationAwareAspectJAutoProxyCreator 注解的apsectj自動代理創建器

class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

@Override

public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {

//往容器中注冊對應的 aspectj注解自動代理創建器

AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);

AnnotationAttributes enableAspectJAutoProxy =

AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);

if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {

AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);

}

if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {

AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);

}

}

}

======================AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);=====

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {

? ? ?return?registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null);

}

//注冊一個AnnotationAwareAspectJAutoProxyCreator(注解適配的切面自動創建器)

public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry, Object source) return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);

}

private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) Assert.notNull(registry, "BeanDefinitionRegistry must not be null");

//判斷容器中有沒有org.springframework.aop.config.internalAutoProxyCreator 名稱的bean定義

if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {

BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);

if (!cls.getName().equals(apcDefinition.getBeanClassName())) {

int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());

int requiredPriority = findPriorityForClass(cls);

if (currentPriority < requiredPriority) {

apcDefinition.setBeanClassName(cls.getName());

}

}

return null;

}

//容器中沒有 那么就注冊一個名稱叫org.springframework.aop.config.internalAutoProxyCreator 類型是AnnotationAwareAspectJAutoProxyCreatorRootBeanDefinition beanDefinition = new RootBeanDefinition(cls);

beanDefinition.setSource(source);

beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);

beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);

return beanDefinition;

}

3)所以我們現在可以分析一下AnnotationAwareAspectJAutoProxyCreator 他是什么一個鬼?

根據上訴類圖

1)我們發現了AnnotationAwareAspectJAutoProxyCreator 有實現了***Aware接口的特性

(BeanFactoryAware)

2)還發現了AnnotationAwareAspectJAutoProxyCreator 實現了BeanPostProcessor接口(后置處理器的特性)

3)還發現了AnnotationAwareAspectJAutoProxyCreator 實現了InstantiationAwareBeanPostProcessor接口(后置

處理器的一種,在實例化之前進行調用)

3)我們根據上AnnotationAwareAspectJAutoProxyCreator 的類的繼承圖來分析

AnnotationAwareAspectJAutoProxyCreator 的功能

3.1)所以我們首先來分析AnnotationAwareAspectJAutoProxyCreator 實現了BeanFactoryAware接口 做了什么工

作?

①:org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator 實現了BeanFactoryAware

我們查看源碼的時候發現AbstractAutoProxyCreator 的setBeanFactory()方法啥都沒有做,但是又被子類覆蓋了

@Override

public void setBeanFactory(BeanFactory beanFactory) {

this.beanFactory = beanFactory;

}

②:AbstractAdvisorAutoProxyCreator覆蓋了AbstractAutoProxyCreator.setBeanFactory()方法

做了二件事情

1:調用父類的super.setBeanFactory(beanFactory);

2:調用本來的initBeanFactory((ConfigurableListableBeanFactory) beanFactory);初始化bean工廠

方法

但是本類的AbstractAdvisorAutoProxyCreator.initBeanFactory()又被子類覆蓋了

public void setBeanFactory(BeanFactory beanFactory) {

//調用父類AbstractAutoProxyCreator.setBeanFactory()方法

super.setBeanFactory(beanFactory);

if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {

throw new IllegalArgumentException(

"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);

}

//初始化bean工程

initBeanFactory((ConfigurableListableBeanFactory) beanFactory);

}

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {

this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);

}

③:AnnotationAwareAspectJAutoProxyCreator#initBeanFactory覆蓋了

AbstractAdvisorAutoProxyCreator.initBeanFactory()方法

//創建一個aop的增強器通過@Apsectj注解的方式.

protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {

//調用父類的

super.initBeanFactory(beanFactory);

//若 apsectj的增強器工廠對象為空,我們就創建一個ReflectiveAspectJAdvisorFactory

if (this.aspectJAdvisorFactory == null) {

this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);

}

//不為空 我們就把aspectJAdvisorFactory 包裝為BeanFactoryAspectJAdvisorsBuilderAdapter

this.aspectJAdvisorsBuilder =

new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);

}

總結:AnnotationAwareAspectJAutoProxyCreator 實現了BeanFactoryAware 也是做了二個事情

事情1:把Beanfactory 保存到AnnotationAwareAspectJAutoProxyCreator 組件上.

事情2: 為AnnotationAwareAspectJAutoProxyCreator 的aspectJAdvisorsBuilder aspect增強器構建器賦值

3.2)還發現了AnnotationAwareAspectJAutoProxyCreator 實現了BeanPostProcessor接口(后置處

理器的特性)

我們追根溯源 AbstractAutoProxyCreator類實現了BeanPostProcessor接口 所以我們分析

BeanPostProcessor的二個方法

①:postProcessBeforeInitialization初始化之前的方法 貌似什么都沒有干

①: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);

if (!this.earlyProxyReferences.contains(cacheKey)) {

//包裝bean 真正的創建代理對象邏輯

return wrapIfNecessary(bean, beanName, cacheKey);

}

}

return bean;

}

3.3)還發現了AnnotationAwareAspectJAutoProxyCreator 實現了InstantiationAwareBeanPostProcessor接口(后

置處理器的一種,在實例化之前進行調用)

我們追根溯源 AbstractAutoProxyCreator類實現了SmartInstantiationAwareBeanPostProcessor

接口 所以我們分析SmartInstantiationAwareBeanPostProcessor的二個方法

①postProcessBeforeInstantiation方法

public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {

Object cacheKey = getCacheKey(beanClass, beanName);

// 判斷TargetSource緩存中是否包含當前bean,如果不包含,則判斷當前bean是否是已經被代理的bean,

// 如果代理過,則不對當前傳入的bean進行處理,如果沒代理過,則判斷當前bean是否為系統bean,或者是

// 切面邏輯不會包含的bean,如果是,則將當前bean緩存到advisedBeans中,否則繼續往下執行。

// 經過這一步的處理之后,只有在TargetSource中沒有進行緩存,并且應該被切面邏輯環繞,但是目前還未

// 生成代理對象的bean才會通過此方法。

if (beanName == null || !this.targetSourcedBeans.contains(beanName)) {

if (this.advisedBeans.containsKey(cacheKey)) {

return null;

}

//若是基礎的class ||或者是否應該跳過 shouldSkip直接返回false

if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {

//把cacheKey 存放在advisedBeans中

this.advisedBeans.put(cacheKey, Boolean.FALSE);

//返回null

return null;

}

}

// 獲取封裝當前bean的TargetSource對象,如果不存在,則直接退出當前方法,否則從TargetSource

// 中獲取當前bean對象,并且判斷是否需要將切面邏輯應用在當前bean上。

if (beanName != null) {

TargetSource targetSource = getCustomTargetSource(beanClass, beanName);

if (targetSource != null) {

this.targetSourcedBeans.add(beanName);

//// 獲取能夠應用當前bean的切面邏輯

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);

//// 根據切面邏輯為當前bean生成代理對象

Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);

this.proxyTypes.put(cacheKey, proxy.getClass());

return proxy;

}

}

return null;

}

=============================判斷是不是基礎的bean=======================================

protected boolean isInfrastructureClass(Class<?> beanClass) {

//是不是Advice PointCut Advisor AopInfrastructureBean 滿足任意返回ture

boolean retVal = Advice.class.isAssignableFrom(beanClass) ||

Pointcut.class.isAssignableFrom(beanClass) ||

Advisor.class.isAssignableFrom(beanClass) ||

AopInfrastructureBean.class.isAssignableFrom(beanClass);

if (retVal && logger.isTraceEnabled()) {

logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");

}

return retVal;

}

②:postProcessAfterInstantiation方法

@Override

public boolean postProcessAfterInstantiation(Object bean, String beanName) {

return true;

}

4)真正的創建代理對象從BeanPostProcessor處理器的后置方法開始

1:>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

2:>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary 有必要的

話進行包裝

3:>org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

4:>org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

5:>org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

6:>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy創建代理對象

4.1)

1:>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#postProcessAfterInitialization

源碼分析

public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {

if (bean != null) {

//通過傳入的class 和beanName生成緩存key

Object cacheKey = getCacheKey(bean.getClass(), beanName);

if (!this.earlyProxyReferences.contains(cacheKey)) {

//若當前bean合適被包裝為代理bean就進行處理

return wrapIfNecessary(bean, beanName, cacheKey);

}

}

return bean;

}

4.2)2:>org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#wrapIfNecessary源碼分

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {

//已經被處理過的 不進行下面的處理

if (beanName != null && this.targetSourcedBeans.contains(beanName)) {

return bean;

}

//不需要被增強的直接返回

if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {

return bean;

}

//判斷當前bean是不是基礎類型的bean,或者指定類型的bean 不需要代理

if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return bean;

}

//獲取通知或者增強器

Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);

//獲取的不為空,生成代理對象

if (specificInterceptors != DO_NOT_PROXY) {

this.advisedBeans.put(cacheKey, Boolean.TRUE);

//創建代理對象

Object proxy = createProxy(

bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));

this.proxyTypes.put(cacheKey, proxy.getClass());

return proxy;

}

//加入advisedBeans集合中

this.advisedBeans.put(cacheKey, Boolean.FALSE);

return bean;

}

/**

* 判斷什么是基礎的class

* */

protected boolean isInfrastructureClass(Class<?> beanClass) {

//判斷當前的class是不是 Pointcut Advisor Advice AopInfrastructureBean 只要有一個滿足就返回true

boolean retVal = Advice.class.isAssignableFrom(beanClass) ||

Pointcut.class.isAssignableFrom(beanClass) ||

Advisor.class.isAssignableFrom(beanClass) ||

AopInfrastructureBean.class.isAssignableFrom(beanClass);

if (retVal && logger.isTraceEnabled()) {

logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]");

}

return retVal;

}

4.3:>org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean

源碼分析

//找到符合條件的增強器

@Override

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) {

//查找符合條件的增強器

List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);

if (advisors.isEmpty()) {

return DO_NOT_PROXY;

}

return advisors.toArray();

}

4.4)org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findEligibleAdvisors

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {

//找到候選的增強器

List<Advisor> candidateAdvisors = findCandidateAdvisors();

//從候選的中選出能用的增強器

List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);

extendAdvisors(eligibleAdvisors);

if (!eligibleAdvisors.isEmpty()) {

eligibleAdvisors = sortAdvisors(eligibleAdvisors);

}

return eligibleAdvisors;

}

4.5)org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findCandidateAdvisors

從IOC容器中查找所有的增強器

protected List<Advisor> findCandidateAdvisors() {

//調用父類獲取增強器

List<Advisor> advisors = super.findCandidateAdvisors();

//解析 @Aspect 注解,并構建通知器

advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());

return advisors;

}

=========================================super.findCandidateAdvisors();=================================

public List<Advisor> findAdvisorBeans() {

//先從緩存中獲取增強器 cachedAdvisorBeanNames是advisor的名稱

String[] advisorNames = this.cachedAdvisorBeanNames;

//緩存中沒有獲取到

if (advisorNames == null) {

//從IOC容器中獲取增強器的名稱

advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(

this.beanFactory, Advisor.class, true, false);

//賦值給增強器緩存

this.cachedAdvisorBeanNames = advisorNames;

}

//在IOC容器中沒有獲取到直接返回

if (advisorNames.length == 0) {

return new ArrayList<Advisor>();

}

List<Advisor> advisors = new ArrayList<Advisor>();

//遍歷所有的增強器

for (String name : advisorNames) {

if (isEligibleBean(name)) {

//忽略正在創建的增強器

if (this.beanFactory.isCurrentlyInCreation(name)) {

if (logger.isDebugEnabled()) {

logger.debug("Skipping currently created advisor '" + name + "'");

}

}

else {

try {

//通過getBean的形式創建增強器 //并且將bean 添加到advisors中

advisors.add(this.beanFactory.getBean(name, Advisor.class));

}

catch (BeanCreationException ex) {

Throwable rootCause = ex.getMostSpecificCause();

if (rootCause instanceof BeanCurrentlyInCreationException) {

BeanCreationException bce = (BeanCreationException) rootCause;

if (this.beanFactory.isCurrentlyInCreation(bce.getBeanName())) {

if (logger.isDebugEnabled()) {

logger.debug("Skipping advisor '" + name +

"' with dependency on currently created bean: " + ex.getMessage());

}

// Ignore: indicates a reference back to the bean we're trying to advise.

// We want to find advisors other than the currently created bean itself.

continue;

}

}

throw ex;

}

}

}

}

return advisors;

}

=============================================aspectJAdvisorsBuilder.buildAspectJAdvisors()解析@Aspject下面buildAspectJAdvisors這個方法為我們做了什么?

第一步:先從增強器緩存中獲取增強器對象

判斷緩存中有沒有增強器對象,有,那么直接從緩存中直接獲取返回出去

沒有.....從容器中獲取所有的beanName

遍歷上一步獲取所有的beanName,通過beanName獲取beanType

根據beanType判斷當前bean是否是一個的Aspect注解類,若不是則不做任何處理

調用advisorFactory.getAdvisors獲取通知器

public List<Advisor> buildAspectJAdvisors() {

//先從緩存中獲取

List<String> aspectNames = this.aspectBeanNames;

//緩存中沒有獲取到

if (aspectNames == null) {

synchronized (this) {

//在嘗試從緩存中獲取一次

aspectNames = this.aspectBeanNames;

//還是沒有獲取到

if (aspectNames == null) {

//從容器中獲取所有的bean的name

List<Advisor> advisors = new LinkedList<Advisor>();

aspectNames = new LinkedList<String>();

String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(

this.beanFactory, Object.class, true, false);

//遍歷beanNames

for (String beanName : beanNames) {

if (!isEligibleBean(beanName)) {

continue;

}

//根據beanName獲取bean的類型

Class<?> beanType = this.beanFactory.getType(beanName);

if (beanType == null) {

continue;

}

//檢查beanType是否包含Aspect

if (this.advisorFactory.isAspect(beanType)) {

aspectNames.add(beanName);

//創建一餓Aspect類的源信息對象

AspectMetadata amd = new AspectMetadata(beanType, beanName);

if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {

MetadataAwareAspectInstanceFactory factory =

new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);

//從aspectj中獲取通知器

List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);

if (this.beanFactory.isSingleton(beanName)) {

this.advisorsCache.put(beanName, classAdvisors);

}

else {

this.aspectFactoryCache.put(beanName, factory);

}

advisors.addAll(classAdvisors);

}

else {

// Per target or per this.

if (this.beanFactory.isSingleton(beanName)) {

throw new IllegalArgumentException("Bean with name '" + beanName +

"' is a singleton, but aspect instantiation model is not singleton");

}

MetadataAwareAspectInstanceFactory factory =

new PrototypeAspectInstanceFactory(this.beanFactory, beanName);

this.aspectFactoryCache.put(beanName, factory);

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

}

this.aspectBeanNames = aspectNames;

return advisors;

}

}

}

//返回空

if (aspectNames.isEmpty()) {

return Collections.emptyList();

}

//緩存中有增強器,我們從緩存中獲取返回出去

List<Advisor> advisors = new LinkedList<Advisor>();

for (String aspectName : aspectNames) {

List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);

if (cachedAdvisors != null) {

advisors.addAll(cachedAdvisors);

}

else {

MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);

advisors.addAll(this.advisorFactory.getAdvisors(factory));

}

}

return advisors;

}

//獲取通知

===========org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory#getAdvisors========

/**

*

*

* */

public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {

//獲取標識了@AspectJ標志的切面類

Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

//獲取切面的名稱

String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();

validate(aspectClass);

// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator

// so that it will only instantiate once.

MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =

new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

List<Advisor> advisors = new ArrayList<Advisor>();

//獲取切面類排除@PointCut標志的所有方法

for (Method method : getAdvisorMethods(aspectClass)) {

//每一個方法都調用getAdvisor方法來獲取增強器

Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);

if (advisor != null) {

advisors.add(advisor);

}

}

// If it's a per target aspect, emit the dummy instantiating aspect.

if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {

Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);

advisors.add(0, instantiationAdvisor);

}

// Find introduction fields.

for (Field field : aspectClass.getDeclaredFields()) {

Advisor advisor = getDeclareParentsAdvisor(field);

if (advisor != null) {

advisors.add(advisor);

}

}

return advisors;

}

//通過方法獲取增強器

public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,

int declarationOrderInAspect, String aspectName) {

validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

//獲取aspectj的切點表達式

AspectJExpressionPointcut expressionPointcut = getPointcut(

candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());

if (expressionPointcut == null) {

return null;

}

//創建advisor實現類

return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,

this, aspectInstanceFactory, declarationOrderInAspect, aspectName);

}

//獲取切點表達式

private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {

//獲取切面注解 @Before @After。。。。。。

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

if (aspectJAnnotation == null) {

return null;

}

//獲取切點表達式對象

AspectJExpressionPointcut ajexp =

new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);

//設置切點表達式

ajexp.setExpression(aspectJAnnotation.getPointcutExpression());

ajexp.setBeanFactory(this.beanFactory);

return ajexp;

}

//找到切面類中方法上的切面注解

protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {

//Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class

for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {

AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);

if (foundAnnotation != null) {

return foundAnnotation;

}

}

return null;

}

//把切點,候選的方法....統一處理生成一個增強器

public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,

Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

this.declaredPointcut = declaredPointcut;

this.declaringClass = aspectJAdviceMethod.getDeclaringClass();

this.methodName = aspectJAdviceMethod.getName();

this.parameterTypes = aspectJAdviceMethod.getParameterTypes();

this.aspectJAdviceMethod = aspectJAdviceMethod;

this.aspectJAdvisorFactory = aspectJAdvisorFactory;

this.aspectInstanceFactory = aspectInstanceFactory;

this.declarationOrder = declarationOrder;

this.aspectName = aspectName;

if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {

// Static part of the pointcut is a lazy type.

Pointcut preInstantiationPointcut = Pointcuts.union(

aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);

// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.

// If it's not a dynamic pointcut, it may be optimized out

// by the Spring AOP infrastructure after the first evaluation.

this.pointcut = new PerTargetInstantiationModelPointcut(

this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);

this.lazy = true;

}

else {

// A singleton aspect.

this.pointcut = this.declaredPointcut;

this.lazy = false;

//實例化切面

this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);

}

}

//獲取advice 切面對象

public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,

MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {

//獲取候選的切面類

Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();

validate(candidateAspectClass);

//獲取切面注解

AspectJAnnotation<?> aspectJAnnotation =

AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);

if (aspectJAnnotation == null) {

return null;

}

// If we get here, we know we have an AspectJ method.

// Check that it's an AspectJ-annotated class

if (!isAspect(candidateAspectClass)) {

throw new AopConfigException("Advice must be declared inside an aspect type: " +

"Offending method '" + candidateAdviceMethod + "' in class [" +

candidateAspectClass.getName() + "]");

}

if (logger.isDebugEnabled()) {

logger.debug("Found AspectJ method: " + candidateAdviceMethod);

}

AbstractAspectJAdvice springAdvice;

//判斷注解的類型

switch (aspectJAnnotation.getAnnotationType()) {

//是切點的返回null

case AtPointcut:

if (logger.isDebugEnabled()) {

logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");

}

return null;

//是不是環繞通知

case AtAround:

springAdvice = new AspectJAroundAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

//是不是前置通知

case AtBefore:

springAdvice = new AspectJMethodBeforeAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

//是不是后置通知

case AtAfter:

springAdvice = new AspectJAfterAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

break;

//返回通知

case AtAfterReturning:

springAdvice = new AspectJAfterReturningAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();

if (StringUtils.hasText(afterReturningAnnotation.returning())) {

springAdvice.setReturningName(afterReturningAnnotation.returning());

}

break;

是不是異常通知

case AtAfterThrowing:

springAdvice = new AspectJAfterThrowingAdvice(

candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);

AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();

if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {

springAdvice.setThrowingName(afterThrowingAnnotation.throwing());

}

break;

default:

throw new UnsupportedOperationException(

"Unsupported advice type on method: " + candidateAdviceMethod);

}

// Now to configure the advice...

springAdvice.setAspectName(aspectName);

springAdvice.setDeclarationOrder(declarationOrder);

/*

* 獲取方法的參數列表名稱,比如方法 int sum(int numX, int numY),

* getParameterNames(sum) 得到 argNames = [numX, numY]

*/

String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);

if (argNames != null) {

//為切面設置參數

springAdvice.setArgumentNamesFromStringArray(argNames);

}

springAdvice.calculateArgumentBindings();

return springAdvice;

}

4.6:)>org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply

//獲取能夠使用的增強器

protected List<Advisor> findAdvisorsThatCanApply(

List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {

ProxyCreationContext.setCurrentProxiedBeanName(beanName);

try {

return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);

}

finally {

ProxyCreationContext.setCurrentProxiedBeanName(null);

}

}

//獲取能使用的增強器

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {

if (candidateAdvisors.isEmpty()) {

return candidateAdvisors;

}

List<Advisor> eligibleAdvisors = new LinkedList<Advisor>();

//遍歷候選的增強器 把他增加到eligibleAdvisors集合中返回

for (Advisor candidate : candidateAdvisors) {

if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {

eligibleAdvisors.add(candidate);

}

}

boolean hasIntroductions = !eligibleAdvisors.isEmpty();

for (Advisor candidate : candidateAdvisors) {

if (candidate instanceof IntroductionAdvisor) {

// already processed

continue;

}

if (canApply(candidate, clazz, hasIntroductions)) {

eligibleAdvisors.add(candidate);

}

}

return eligibleAdvisors;

}

//判斷是當前的增強器是否能用 通過方法匹配來計算當前是否合適當前類的增強器

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {

if (advisor instanceof IntroductionAdvisor) {

return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);

}

else if (advisor instanceof PointcutAdvisor) {

PointcutAdvisor pca = (PointcutAdvisor) advisor;

return canApply(pca.getPointcut(), targetClass, hasIntroductions);

}

else {

// It doesn't have a pointcut so we assume it applies.

return true;

}

}

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {

Assert.notNull(pc, "Pointcut must not be null");

if (!pc.getClassFilter().matches(targetClass)) {

return false;

}

//創建一個方法匹配器

MethodMatcher methodMatcher = pc.getMethodMatcher();

if (methodMatcher == MethodMatcher.TRUE) {

// No need to iterate the methods if we're matching any method anyway...

return true;

}

//包裝方法匹配器

IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;

if (methodMatcher instanceof IntroductionAwareMethodMatcher) {

introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;

}

//獲取本來和接口

Set<Class<?>> classes = new LinkedHashSet<Class<?>>(ClassUtils.getAllInterfacesForClassAsSet(targetClass));

classes.add(targetClass);

//循環classes

for (Class<?> clazz : classes) {

//獲取所有的方法 進行匹配

Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);

for (Method method : methods) {

if ((introductionAwareMethodMatcher != null &&

introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) ||

methodMatcher.matches(method, targetClass)) {

return true;

}

}

}

return false;

}

4.5)org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator#createProxy創建代理對象

protected Object createProxy(

Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {

//判斷容器的類型ConfigurableListableBeanFactory

if (this.beanFactory instanceof ConfigurableListableBeanFactory) {

AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);

}

//創建代理工程

ProxyFactory proxyFactory = new ProxyFactory();

proxyFactory.copyFrom(this);

/*

* 默認配置下,或用戶顯式配置 proxy-target-class = "false" 時,

* 這里的 proxyFactory.isProxyTargetClass() 也為 false

*/

if (!proxyFactory.isProxyTargetClass()) {

if (shouldProxyTargetClass(beanClass, beanName)) {

proxyFactory.setProxyTargetClass(true);

}

else {

/*

* 檢測 beanClass 是否實現了接口,若未實現,則將

* proxyFactory 的成員變量 proxyTargetClass 設為 true

*/

evaluateProxyInterfaces(beanClass, proxyFactory);

}

}

//獲取容器中的方法增強器

Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);

proxyFactory.addAdvisors(advisors);

proxyFactory.setTargetSource(targetSource);

customizeProxyFactory(proxyFactory);

proxyFactory.setFrozen(this.freezeProxy);

if (advisorsPreFiltered()) {

proxyFactory.setPreFiltered(true);

}

//創建代理對象

return proxyFactory.getProxy(getProxyClassLoader());

}

public Object getProxy(ClassLoader classLoader) {

return createAopProxy().getProxy(classLoader);

}

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {

if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {

Class<?> targetClass = config.getTargetClass();

if (targetClass == null) {

throw new AopConfigException("TargetSource cannot determine target class: " +

"Either an interface or a target is required for proxy creation.");

}

//是否實現了接口

if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {

//jdk代理

return new JdkDynamicAopProxy(config);

}

//cglib代理

return new ObjenesisCglibAopProxy(config);

}

else {

jdk代理

return new JdkDynamicAopProxy(config);

}

}

public Object getProxy(ClassLoader classLoader) {

if (logger.isDebugEnabled()) {

logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());

}

Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);

findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);

//創建jdk代理對象

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

}

5:代理對象調用目標方法

背景知識:

@EnableAspectJAutoProxy(exposeProxy = true) 這個東東是用來干什么的?

沒有配置exposeProxy 暴露代理對象的時候我們方法調用

我們在Mod方法中 通過this來調用本類的方法add()方法的時候,發現add()的方法不會被攔截

而我們配置了后exposeProxy的屬性,我們發現可以通過

int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);

調用的時候,發現了add()方法可以被攔截

原理:把這個exposeProxy設置為true,會把代理對象存放在線程變量中,

AopContext.currentProxy())是從線程變量中獲取代理對象(源碼中分析)

應用場景(事物方法調用事物方法需要二個都起作用需要配置這個東東)

public interface Calculate {

/**

* 加法

* @param numA

* @param numB

* @return

*/

int add(int numA,int numB);

/**

* 減法

* @param numA

* @param numB

* @return

*/

int reduce(int numA,int numB);

/**

* 除法

* @param numA

* @param numB

* @return

*/

int div(int numA,int numB);

/**

* 乘法

* @param numA

* @param numB

* @return

*/

int multi(int numA,int numB);

int mod(int numA,int numB);

}

public class TulingCalculate implements Calculate {

public int add(int numA, int numB) {

return numA+numB;

}

public int reduce(int numA, int numB) {

return numA-numB;

}

public int div(int numA, int numB) {

return numA/numB;

}

public int multi(int numA, int numB) {

return numA*numB;

}

public int mod(int numA,int numB){

int retVal = ((Calculate) AopContext.currentProxy()).add(numA,numB);

//int retVal = this.add(numA,numB);

return retVal%numA;

}

}

代理對象調用源代碼:

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

MethodInvocation invocation;

Object oldProxy = null;

boolean setProxyContext = false;

TargetSource targetSource = this.advised.targetSource;

Class<?> targetClass = null;

Object target = null;

try {

Object retVal;

//是否暴露代理對象

if (this.advised.exposeProxy) {

//把代理對象添加到TheadLocal中

oldProxy = AopContext.setCurrentProxy(proxy);

setProxyContext = true;

}

//獲取被代理對象

target = targetSource.getTarget();

if (target != null) {

//設置被代理對象的class

targetClass = target.getClass();

}

//把增強器轉為方法攔截器鏈

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

//若方法攔截器鏈為空

if (chain.isEmpty()) {

//通過反射直接調用目標方法

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);

}

else {

//創建方法攔截器調用鏈條

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

//執行攔截器鏈

retVal = invocation.proceed();

}

//獲取方法的返回值類型

Class<?> returnType = method.getReturnType();

if (retVal != null && retVal == target &&

returnType != Object.class && returnType.isInstance(proxy) &&

!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {

//如果方法返回值為 this,即 return this; 則將代理對象 proxy 賦值給 retVal

retVal = proxy;

}

//如果返回值類型為基礎類型,比如 int,long 等,當返回值為 null,拋出異常

else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {

throw new AopInvocationException(

"Null return value from advice does not match primitive return type for: " + method);

}

return retVal;

}

finally {

if (target != null && !targetSource.isStatic()) {

// Must have come from TargetSource.

targetSource.releaseTarget(target);

}

if (setProxyContext) {

// Restore old proxy.

AopContext.setCurrentProxy(oldProxy);

}

}

}

=====================org.springframework.aop.framework.AdvisedSupport#getInterceptorsAndDynamicInterceptionAdvice===========

把增強器中轉為方法攔截器鏈

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {

//從緩存中獲取緩存key 第一次肯定獲取不到

MethodCacheKey cacheKey = new MethodCacheKey(method);

//通過cacheKey獲取緩存值

List<Object> cached = this.methodCache.get(cacheKey);

//從緩存中沒有獲取到

if (cached == null) {

//獲取所有的攔截器

cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(

this, method, targetClass);

//放入緩存.....

this.methodCache.put(cacheKey, cached);

}

return cached;

}

=====================org.springframework.aop.framework.AdvisorChainFactory#getInterceptorsAndDynamicInterceptionAdvice====

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(

Advised config, Method method, Class<?> targetClass) {

//創建攔截器集合長度是增強器的長度

List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);

Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());

boolean hasIntroductions = hasMatchingIntroductions(config, actualClass);

AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();

//遍歷所有的增強器集合

for (Advisor advisor : config.getAdvisors()) {

//判斷增強器是不是PointcutAdvisor

if (advisor instanceof PointcutAdvisor) {

//把增強器轉為PointcutAdvisor

PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;

//通過方法匹配器對增強器進行匹配

if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {

MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();

//能夠匹配

if (MethodMatchers.matches(mm, method, actualClass, hasIntroductions)) {

//把增強器轉為攔截器

MethodInterceptor[] interceptors = registry.getInterceptors(advisor);

if (mm.isRuntime()) {

// Creating a new object instance in the getInterceptors() method

// isn't a problem as we normally cache created chains.

for (MethodInterceptor interceptor : interceptors) {

interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));

}

}

else {

interceptorList.addAll(Arrays.asList(interceptors));

}

}

}

}

else if (advisor instanceof IntroductionAdvisor) {

IntroductionAdvisor ia = (IntroductionAdvisor) advisor;

if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {

Interceptor[] interceptors = registry.getInterceptors(advisor);

interceptorList.addAll(Arrays.asList(interceptors));

}

}

else {

Interceptor[] interceptors = registry.getInterceptors(advisor);

interceptorList.addAll(Arrays.asList(interceptors));

}

}

return interceptorList;

}

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容