一、在applicationContext的beanFactory.preInstantiateSingletons方法中,会初始化所有的单例BEAN.
二、
1.AbstractAutowireCapableBeanFactory.doCreateBean在调用BEAN默认构造函数反射生成实例对象后,会populateBean填充属性,
2.如果属性是通过AUTOWIRED或者RESOURCE依赖注入时,则会触发CommonAnnotationBeanPostProcessor的处理器,此处理器会再次去BEAN工厂获取属性BEAN,不存在则再次调用createBean创建。
3.在实例化完属性对象后,会调用AbstractAutowireCapableBeanFactory.initializeBean再次对BEAN进行后置处理,
4.然后又会调用AnnotationAwareAspectJAutoProxyCreator.postProcessAfterInitialization对BEAN对象进行修改。
5.最后调用AbstractAutoProxyCreator.createProxy创建代理对象。此函数创建代理对象时会传入所有当前系统注册的切面注入到代理对象,ExposeInvocationInterceptor--这个是系统默认的拦截对象。
三、实际生成cglib/jdk proxy object,的流程。
1.接上面最后一步,在public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport这个类中,会调用createAopProxy().getProxy(classLoader)
2.createAopProxy()会调用getAopProxyFactory().createAopProxy(this);这个接口返回的对象为
AopProxy,有两种实现,分为CglibAopProxy,JdkDynamicAopProxy
getAopProxyFactory为DefaultAopProxyFactory
3.CglibAopProxy的getProxy接口来生成实际的CGLIB或者 JDK代理类。生成代理类中会设置一系列的callback
就是拦截器,也就是系统容器中定义的通知处理方法(如执行前,执行后,环绕,返回前,抛出异常前)。
package com.tpw.newday.aspect;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.tpw.newday.annation.CacheProcesser;
import com.tpw.newday.common.MyConstants;
import com.tpw.newday.redis.RedisParam;
import com.tpw.newday.redis.RedisService;
import com.tpw.newday.utils.RedisUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.stereotype.Component;
import java.lang.reflect.Method;
/**
* <h3>newday</h3>
* <p>xx</p>
*
* @author : lipengyao
* @date : 2021-04-30 15:56:19
**/
@Aspect
@Component
public class CacheAspect {
private static final Log logger = LogFactory.getLog(CacheAspect.class);
private RedisUtil redisUtil = new RedisUtil(MyConstants.redis_host_ip,MyConstants.redis_port,MyConstants.redis_password);
@Autowired
private RedisService redisService;
@Pointcut("execution(* com.tpw.newday.service..*.*(..)))")
private void cacheMethod() {
}
/**
* 前置通知:在目标方法执行前调用
*/
@Before("cacheMethod()")
public void begin() {
logger.info("==@Before== lipy cache method : begin");
}
/**
* 后置通知:在目标方法执行后调用,若目标方法出现异常,则不执行
*/
@AfterReturning("cacheMethod()")
public void afterReturning() {
logger.info("==@AfterReturning== lipy cache method : after returning");
}
/**
* 后置/最终通知:无论目标方法在执行过程中出现一场都会在它之后调用
*/
@After("cacheMethod()")
public void after() {
logger.info("==@After== lipy cache method : finally returning");
}
/**
* 异常通知:目标方法抛出异常时执行
*/
@AfterThrowing("cacheMethod()")
public void afterThrowing() {
logger.info("==@AfterThrowing== lipy cache method : after throwing");
}
/**
* 环绕通知:灵活自由的在目标方法中切入代码
*/
@Around("cacheMethod()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取目标方法的名称
String methodName = joinPoint.getSignature().getName();
// 获取方法传入参数
Object[] params = joinPoint.getArgs();
logger.info("==@Around== lipy cache method --》 method name " + methodName + " args " + params[0]);
return handleMethod(joinPoint);
}
/**
* 获取redis的key
*/
private String parseKey(String fieldKey, Method method, Object[] args) {
//获取被拦截方法参数名列表(使用Spring支持类库)
LocalVariableTableParameterNameDiscoverer u = new LocalVariableTableParameterNameDiscoverer();
String[] paraNameArr = u.getParameterNames(method);
//使用SPEL进行key的解析
ExpressionParser parser = new SpelExpressionParser();
//SPEL上下文
StandardEvaluationContext context = new StandardEvaluationContext();
//把方法参数放入SPEL上下文中
for (int i = 0; i < paraNameArr.length; i++) {
context.setVariable(paraNameArr[i], args[i]);
}
String key= parser.parseExpression(fieldKey).getValue(context, String.class);
return key;
}
/**
* 获取方法中声明的注解
*
* @param joinPoint
* @return
* @throws NoSuchMethodException
*/
public Object handleMethod(ProceedingJoinPoint joinPoint) throws Throwable {
// 获取方法名
String methodName = joinPoint.getSignature().getName();
// 反射获取目标类
Class<?> targetClass = joinPoint.getTarget().getClass();
// 拿到方法对应的参数类型
Class<?>[] parameterTypes = ((MethodSignature) joinPoint.getSignature()).getParameterTypes();
// 根据类、方法、参数类型(重载)获取到方法的具体信息
Method objMethod = targetClass.getMethod(methodName, parameterTypes);
// 获取方法传入参数
Object[] params = joinPoint.getArgs();
// 拿到方法定义的注解信息
CacheProcesser annotation = objMethod.getDeclaredAnnotation(CacheProcesser.class);
if (ObjectUtil.isNull(annotation)){
// 执行源方法
return joinPoint.proceed();
}
if (annotation.cacheOperation() == CacheProcesser.CacheOperation.QUERY){
String cacheKey = annotation.key()+ ":"+this.parseKey(annotation.fieldKey(),objMethod ,params );
RedisParam redisParam = new RedisParam(cacheKey,annotation.expireTime());
Object cacheResult = redisService.get(redisParam);
if (ObjectUtil.isNotNull(cacheResult)){
logger.info(" get from cache key:" + cacheKey);
return cacheResult;
}else{
Object obj = joinPoint.proceed();
redisService.set(redisParam,obj );
logger.info(" call method,set to cache key:" + cacheKey);
return obj;
}
}else if (annotation.cacheOperation() == CacheProcesser.CacheOperation.UPDATE ||
annotation.cacheOperation() == CacheProcesser.CacheOperation.DELETE ){
Object obj = joinPoint.proceed();
String cacheKey = annotation.key()+ ":"+this.parseKey(annotation.fieldKey(),objMethod ,params );
RedisParam redisParam = new RedisParam(cacheKey,annotation.expireTime());
logger.info(" delete from cache key:" + cacheKey);
redisService.remove(redisParam);
return obj;
}
return joinPoint.proceed();
}
}
4.最终把cglib或者JDK生成的代理类注入到属性中,或者返回给创建者。
四、最终HTTP请求调用过时,调用服务类接口时,首先会调用到代理类的方法。
1.上述接口会先调用DynamicAdvisedInterceptor.intercept方法,此接口实现了cglib的
MethodInterceptor方法,会被CGLIB反向调用。
2.上述方法内会调用 retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(), CglibMethodInvocation 会继承于 ReflectiveMethodInvocation,最终触发到
ReflectiveMethodInvocation.proceed()
3.ReflectiveMethodInvocation内有一个拦截器数组interceptorsAndDynamicMethodMatchers,存储了所有的切面方法,会根据索引逐个调用,拦截器内部又会再次调用此对象的ReflectiveMethodInvocation.proceed,调到下一个拦截器,
拦截器列表:
4.如果拦截器调用完,则会调用最终的methodProxy方法。