1、AOP基本概念
-
(1). A spect 【切面】:通常是一个类,里面可以定义切入点和通知;
-
(2). JointPoint 【连接点】:程序执行过程中明确的点,一般是方法的调用;
-
(3). Advice 【通知】:AOP在特定的切入点上执行的增强的处理,有before/after/around/afterRetuing/afterThrowing;
-
(4). PointCut (切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式。
-
(5). Excution 表达式:定义切入点规则,多个方法形成一个切面;
-
第一个*:代表的是方法返回的类型
-
第二个*: 代表扫描的包路径;
-
第三个*:包路径下的方法名,(..)代表方法的参数;
@Around("@annotation(com.king..LogAspect)") //容器中加了LogAspect注解的类才拦截;
@Before("execution(public int com.king.aop.Calc.div(int,int))") //拦截div(intent)方法,返回参数是int;
@Before("execution(public int com.king.aop.Calc.*(..))") //拦截包下的所有的方法;
@Around("execution(public int com.king.aop.Calc.*(..)) && @annotation(log)") //将注解 DoSomething作为一个参数传递进来
2、AOP应用场景
-
Spring中各种注解功能的实现,例如事务@Transactional/@Async/@Aspect等等太多,使业务和功能代码解耦,进行无侵入性的代码增强;
-
统一请求、参数校验,日志和异常处理;
-
权限验证,数据源的切换等等;
3、AOP的实践
@Component
@Aspect
public class LogAspect {
//抽取公共切入点表达式
//1 如果是该应用内,只需要@Before("pointCut()")
//2 如果是其他切面类需要引用,需要写上切面类的路径和方法
@Pointcut("execution(public int com.king.aop.Calc.*(..))")
public void pointCut() {
}
@Before("execution(public int com.king.aop.Calc.div(int,int))")
public void logStart(JoinPoint joinPoint) {
System.out.println("Before 除法运行开始,方法名:" + joinPoint.getSignature().getName() + " 参数列表: {" +
Arrays.asList(joinPoint.getArgs()) + "}");
}
@After("pointCut()")
public void logEnd() {
System.out.println("After 除法运行结束。。。。");
}
@AfterReturning(value = "com.king.aop.LogAspect.pointCut()", returning = "result")
public void logReturn(Object result) {
System.out.println("AfterReturning 除法正常返回,结果为:" + result);
}
//测试分母为0的异常情况
@AfterThrowing(value = "pointCut()", throwing = "exception")
public void logAfterThrowing(Exception exception) {
System.out.println("AfterThrowing 除法运算异常 " + exception);
}
@Around(value = "pointCut() && @annotation(logAnnotation) ")
public Object logAround(ProceedingJoinPoint proceedingJoinPoint,BaseLog logAnnotation) {
System.out.println("logAround 执行目标方法之前: ");
try {//这里必须手动调用
Object obj = proceedingJoinPoint.proceed();
System.out.println("logAround 目标方法执行之后: ");
return obj;
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return -1;
}
}
切面注解
@Target({ElementType.METHOD,ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
public @interface BaseLog {
}
-
一类是 java 自带的标准注解:包括常用的@Controller @Service @Repository
-
二类是元注解,元注解是用于定义注解的注解,包括
-
@Retention(表明注解被保留的阶段) 源代码-编译器 - 运行期 什么作用范围,生命周期?
-
@targe(标明注解使用的范围) 什么范围使用?
-
@Inherited(标明注解可继承) 能否被继承?
-
@Documented(标明是否生成javadoc文档) 是否包含在javadoc中?
-
-
三类是自定义注解,根据自己的定义需求注解
-
source:存在java代码级别,编译为class就无效了; @Override,格式检查,是否覆盖实现了接口的方法
-
class:编译期级别,帮我们生成get和set方法; lambook @Data
-
Runtime类型:运行期间产生作用 @Service,很常见
拦截方法
public class Calc {
//业务逻辑
@BaseLog
public int div(int i, int j) {
return i / j;
}
}
配置类
@Configuration
@EnableAspectJAutoProxy
public class ConfigAop {
@Bean
public Calc getCalc(){
return new Calc();
}
@Bean
public LogAspect getAspect(){
return new LogAspect();
}
}
测试类:
@Test
public void aopTest() {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(com.aop.ConfigAop.class);
Calc calc = app.getBean(Calc.class);
System.out.println("result: "+ calc.div(8, 2));
}
正常运行结果8/2:
logAround 执行目标方法之前:
Before 除法运行开始,方法名:div 参数列表: {[8, 2]}
div running
logAround 目标方法执行之后:
After 除法运行结束。。。。
AfterReturning 除法正常返回,结果为:4
result: 4
异常运行:输入2/0的结果:
logAround 执行目标方法之前:
Before 除法运行开始,方法名:div 参数列表: {[2, 0]}
div running
java.lang.ArithmeticException: / by zero
at com.enjoy.aop.aop.Calc.div(Calc.java:15)
After 除法运行结束。。。。
AfterReturning 除法正常返回,结果为:-1
reslut: -1
通过调试,你会发现Calc是经过增强的Bean,它其实变成了一个实现了Advised接口的代理类,并不是原生的Calc类,所以才会运行自己编写的切面类。
4、AOP 切面执行顺序分析
try
{
1、 环绕前置通知;@Around
2、 前置通知; @Before
3、 执行目标方法; method.invoke()
4、 环绕后置通知;@Around
5、 执行返回通知;@After
}catche(Exception e){
5.1、执行异常通知;@AfterThrowing 没有异常不打印,有异常替换@After
}finally{
6、执行后置通知;@AfterReturning
}
AOP的执行流程图如下:
[Aspect-1] logAround 执行目标方法之前:
[Aspect-1] Before 除法运行开始:div 参数列表: {[8, 2]}
[Aspect-2] logAround 执行目标方法之前:
[Aspect-2] Before 除法运行开始:div 参数列表: {[8, 2]}
Ok
[Aspect-2] logAround 目标方法执行之后:
[Aspect-2] After 除法运行结束。。。。
[Aspect-2] AfterReturning 除法正常返回,结果为:4
[Aspect-1] logAround 目标方法执行之后:
[Aspect-1] After 除法运行结束。。。。
[Aspect-1] AfterReturning 除法正常返回,结果为:4
如果要确定两个切面的执行顺序,可以给aspect添加@Order注解,值越小优先级越高。
@Order(1)
@Component
@Aspect
public class ParamCheckAspect1 {
// ...
}
@Order(2)
@Component
@Aspect
public class LogAspect2 {
// ...
}
这样就先执行参数校验的切面ParamCheckAspect1,然后执行日志打印的切面拦截LogAspect2,控制了其执行顺序。
5、AOP使用注意事项
@Test
public void aopTest() {
AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(com.aop.ConfigAop.class);
Calc calc = new Calc();
System.out.println("result: "+ calc.div(8, 2)); //这时候日志的切面是不生效的,没有被spring代理,没有增强;
}
2、Final方法不能被通知,因为它final不能被重写,动态代理的CGlib不能重写final方法;
3、对于@Around这个注解,不管它有没有返回值,内部都必须要调用一下pjp.proceed(),否则目标方法将不会执行,也就是@Before无法执行;如果我们去掉这个执行方法,运行结果如下:
注释掉://Object obj = proceedingJoinPoint.proceed();
@Before和目标方法不会执行,运行结果:
logAround 执行目标方法之前:
logAround 目标方法执行之后:
After 除法运行结束。。。。
AfterReturning 除法正常返回,结果为:-1
reslut: -1
可以看到,结果打印没有方法的执行。
6、AOP的设计思想
-
第一步:首先创建AOP后置处理器- AnnotationAwareAspectJAutoProxyCreator,加工增强我们的bean;因为它要对业务bean的创建进行拦截,必须先创建;
-
第二步:然后再创建剩余的单实例bean,业务bean;
-
第三步:接着在创建单实例业务bean进行初始化的时候,通过后置处理器postProcessor就会对其做增强;
-
第四步:通过动态代理的到一个增强的代理对象;
-
第五步:通过代理对象来执行目标方法 , CglibAopProxy. intercept() + proceed();
-
(1) 得到目标方法的拦截器链(增强器包装成拦截器 MethodInterceptor );
-
(2) 利用拦截器链式机制,一次进入每一个拦截器进行执行;
-
(3) 执行结果顺序:
-
正常执行:环绕前置通知AroundBefore -> 前置通知Before-> 环绕后置通知AroundAfter -> 目标方法invoke() -> 后置通知After -> 返回通知 AfterReturning
-
异常执行:环绕前置通知 AroundBefore -> 前置通知 Before -> 环绕后置通知 AroundAfter -> 目标方法 invoke() -> 异常通知 AfterThrowing
-
-
7、源码解析
@Configuration
@EnableAspectJAutoProxy
public class ConfigAop {
@Bean
public Calc getCalc(){
return new Calc();
}
@Bean
public LogAspect getAspect(){
return new LogAspect();
}
}
7.1、后置处理器AnnotationAwareAspectJAutoProxyCreator的创建
@Target(ElementType.TYPE) //在什么地方使用?方法/类/字段
@Retention(RetentionPolicy.RUNTIME) //什么时间生效?class文件 @override- - 编译期间 lambook- 运行期间
@Documented //是否加入到javaDoc中
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
//判断是用jdk还是CGLib动态代理
boolean proxyTargetClass() default false;
//是否暴露aop动态代理,在同类中动态代理的方法调用的时候就需要用到它;
boolean exposeProxy() default false;
}
继续查看AspectAutoProxyRegistrar源码,发现其通过ImportBeanDefinitionRegistrar向容器中注入了一个十分重要的组件:AnnotationAwareAspectJAutoProxyCreator.class,它贯穿了整个aop的全过程;
class AspectJAutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
/**
* Register, escalate, and configure the AspectJ auto proxy creator based on the value
* of the @{@link EnableAspectJAutoProxy#proxyTargetClass()} attribute on the importing
* {@code @Configuration} class.
*/
@Override
public void registerBeanDefinitions(
AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
AopConfigUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry);
AnnotationAttributes enableAspectJAutoProxy =
AnnotationConfigUtils.attributesFor(importingClassMetadata, EnableAspectJAutoProxy.class);
if (enableAspectJAutoProxy != null) {
if (enableAspectJAutoProxy.getBoolean("proxyTargetClass")) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
}
if (enableAspectJAutoProxy.getBoolean("exposeProxy")) {
AopConfigUtils.forceAutoProxyCreatorToExposeProxy(registry);
}
}
}
}@Nullable
public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
//开始向容器中注入组件:AnnotationAwareAspectJAutoProxyCreator
return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source);
}
看一下AnnotationAwareAspectJAutoProxyCreator的作用?
public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
从这里可以看出,它是一个后置处理器;主要关注我们的bean初始化的前后需要做的事情,自动装配BeanFactory
7.2、增强业务Bean的创建
public class Calc {
//业务逻辑
@BaseLog
public int div(int i, int j) {
return i / j;
}
}
一切从容器的启动refresh开始:
@Override
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
//调用所有注册的BeanFactoryPostProcessor的Bean定义信息,但是未创建未初始化;
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
//BeanPostProcessor是Bean后置处理器的创建,用于监听容器触发的事件aop相关bean的创建,aop相关的bean就是在这里注册创建实例化;
//AnnotationAwareAspectJAutoProxyCreator.class就是在这里创建实例化;
registerBeanPostProcessors(beanFactory);
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
//相关业务bean的创建,也就是计算类calc类的创建
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
创建剩余的保留的单实例bean:
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
// Initialize conversion service for this context.
if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&
beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {
beanFactory.setConversionService(
beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));
}
// Instantiate all remaining (non-lazy-init) singletons.
beanFactory.preInstantiateSingletons();
}
继续初始化bean:
@Override
public void preInstantiateSingletons() throws BeansException {
String FACTORY_BEAN_PREFIX = "&";
//得到所有的bean的名字
List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);
// Trigger initialization of all non-lazy singleton beans...
for (String beanName : beanNames) {
RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);
if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {
if (isFactoryBean(beanName)) {
Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);
if (bean instanceof FactoryBean) {
final FactoryBean<?> factory = (FactoryBean<?>) bean;
boolean isEagerInit;
if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {
isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>)
((SmartFactoryBean<?>) factory)::isEagerInit,
getAccessControlContext());
}
else {
isEagerInit = (factory instanceof SmartFactoryBean &&
((SmartFactoryBean<?>) factory).isEagerInit());
}
if (isEagerInit) {
getBean(beanName);
}
}
}
else {//循环获取这个bean
getBean(beanName);
}
}
}
继续getBean():
@Override
public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
这里主要关注 Calculator的创建,是如何增强的?
protected <T> T doGetBean(final String name, @Nullable final Class<T> requiredType,
@Nullable final Object[] args, boolean typeCheckOnly) throws BeansException {
final String beanName = transformedBeanName(name);
Object bean;
// Eagerly check singleton cache for manually registered singletons.
Object sharedInstance = getSingleton(beanName);
if (sharedInstance != null && args == null) {
// Create bean instance. //创建bean实例
if (mbd.isSingleton()) {
//第一次根据bean name去拿单实例bean,肯定没有
sharedInstance = getSingleton(beanName, () -> {
try {//创建bean实例
return createBean(beanName, mbd, args);
}
}
获取calculator的bean,并判断有无增强处理:
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)
throws BeanCreationException {
try {
// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.
//给个机会返回代理类对象;
//对bean的前置处理器,遍历出所有的postProcessBean;
Object bean = resolveBeforeInstantiation(beanName, mbdToUse);
//第一步:创建一个单实例bean;普通的实例bean
if (bean != null) {
return bean;
}
}
try { //第二步:后置处理器返回一个动态代理
Object beanInstance = doCreateBean(beanName, mbdToUse, args);
if (logger.isTraceEnabled()) {
logger.trace("Finished creating instance of bean '" + beanName + "'");
}
return beanInstance;
}
@Nullable //初始化之前判断是否有后置处理器的增强;
protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) {
Object bean = null;
if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) {
// Make sure bean class is actually resolved at this point.
//判断该bean Calcutor是否是实现了BeanPostProcessor,显然满足条件是一个后置处理,加了aop的功能
if (!mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
Class<?> targetType = determineTargetType(beanName, mbd);
if (targetType != null) {
//前置处理器
bean = applyBeanPostProcessorsBeforeInstantiation(targetType, beanName);
if (bean != null) {
//后置处理器
bean = applyBeanPostProcessorsAfterInitialization(bean, beanName);
}
}
}
mbd.beforeInstantiationResolved = (bean != null);
}
return bean;
}
// 找到Calcutor的后置处理器 AnnotationAwareAspectJAutoProxyCreator 进行增强;
//前置处理器主要是 拿到@Aspect中的所有切面方法
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
//拿到bean的名字,cachekey ==Calcutor
Object cacheKey = getCacheKey(beanClass, beanName);
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
//找到 Calcutor 的增强器,主要是拦截的4个切面类
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy; //至此-返回一个代理对象,但是before不会产生任何代理
}
}
//找 Calcutor的增强器
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//获取合适的增强器,就是我们编写的before - after - around的切面类
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对增强器进行排序,因为方法调用是有时机顺序的,前面也提到验证过,before-after-return
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
通过反射创建一个增强的代理bean,最后生成的这个Bean就是加入切面类增强的Bean。
*/
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final @Nullable Object[] args)
throws BeanCreationException {
// Instantiate the bean.
BeanWrapper instanceWrapper = null;
if (mbd.isSingleton()) {
instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);
} // 第一步:通过反射创建bean
if (instanceWrapper == null) {
instanceWrapper = createBeanInstance(beanName, mbd, args);
}
Object exposedObject = bean;
try {
//第二步:给实例bean赋值
populateBean(beanName, mbd, instanceWrapper);
//第三步:给bean初始化
exposedObject = initializeBean(beanName, exposedObject, mbd);
}
进入到后置处理器:
protected Object initializeBean(final String beanName, final Object bean, @Nullable RootBeanDefinition mbd) {
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {//初始化前置处理器
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try { //调用方法
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {//初始化后置处理器
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
进入后置处理器,后置处理器的作用:
-
拿到所有的通知方法;
-
创建增强的动态代理对象;Calcutor对象;
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//从缓存中拿到bean的名字
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (!this.earlyProxyReferences.contains(cacheKey)) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
如果对象有增强,找到增强器,因为切面类不是实现的接口,所以开始通过Cglib创建代理对象:
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
// Create proxy if we have advice. //先获取排好序的通知类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;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
//创建动态代理类,创建aop增强bean的创建
public class DefaultAopProxyFactory implements AopProxyFactory, Serializable {
@Override
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 {
return new JdkDynamicAopProxy(config);
}
}
}
至此,我们的增强bean Calc就创建完成了。
7.3、调用执行阶段
//通过cglib创建动态代理类,获取相关的切面拦截方法
class CglibAopProxy implements AopProxy, Serializable {
// Constants for CGLIB callback array indices
private static final int AOP_PROXY = 0;
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
//第一步:拿到我们的目标类:calculator类;
TargetSource targetSource = this.advised.getTargetSource();
try {//暴露动态代理,同类里调用事务注解失效就是在这里设置解决的;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
//第二步:拿到拦截链
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// We need to create a method invocation…
//第三步:调用具体的方法,around的时候需要手动的调用我们的方法,proceed()就是调用方法本身;
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
获取拦截链的拦截通知方法,也就是Aspect中写的拦截方法,这里获取到:
@Override//拿到所有的通知方法
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
//第一步:拿到通知方法的长度
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
if (match) {
//第二步:将Inteceptor转换为MethodInterceptor
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));
}
}
return interceptorList;
}
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
//第一步:通过i++来取我们的通知拦截方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
//第二步:栈式方法调用
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
到此,我们创建和执行阶段就完全解析完了。虽然搞了好久,不过好似打通了任督二脉,舒坦。
8、小结
-
第一步:通过@Enablexxxx来为容器中先注册一个有关功能的代理创建器@xxxAutoProxyCreator,一般这个处理器会实现我们的后置处理器接口postProcessor;
-
第二步:实例化我们的业务bean,通过后置处理器postProcessor在bean初始化后的afterInitialized对bean进行增强;通过动态代理创建增强bean注入到容器;
-
第三步:通过动态代理调用我们的增强的bean代理对像,实现增强的业务功能;