动态代理-浅谈SpringAOP

JDK InvocationHandler --> CGLIB MethodInterceptor --> SpringAOP的底层 ProxyFactory --> bean初始化后生成代理的源码 --> @Aspect相关切面注解

1. jdk动态代理

// 接口
public interface OrderService {
    String say();
}

// 实现类 结果为: "order service impl"
public class OrderServiceImpl implements OrderService {
    @Override
    public String say() {
        return "order service impl";
    }
}

// JDK动态代理
public class InvocationHandlerImpl implements InvocationHandler {

    private Object needProxyObj;

    public InvocationHandlerImpl(Object needProxyObj) {
        this.needProxyObj = needProxyObj;
    }

	// 针对方法 做切面
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("invoke before");
        Object result = method.invoke(needProxyObj, args);
        System.out.println("proxy return string : " + result);
        System.out.println("invoke finished");
        return result;
    }
}

// 测试代理
public class InvocationTest {

    public static void main(String[] args) {
    	// 代理是运行时的 设置 生成文件
        System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
        
        OrderServiceImpl orderService = new OrderServiceImpl();
        InvocationHandlerImpl invocationHandler = new InvocationHandlerImpl(orderService);
		// 生成代理
        OrderService proxyOrderService = (OrderService) Proxy.newProxyInstance(orderService.getClass().getClassLoader(), orderService.getClass().getInterfaces(), invocationHandler);
        proxyOrderService.say();
    }
}
输出结果如下
Connected to the target VM, address: '127.0.0.1:62695', transport: 'socket'
invoke before
proxy return string : order service impl
invoke finished
Disconnected from the target VM, address: '127.0.0.1:62695', transport: 'socket'

2. cglib代理

// 定义一个类
public class OrderServiceImpl {
    public String say() {
        return "order service impl";
    }
}

// 实现MethodInterceptor
public class MyMethodInterceptor implements MethodInterceptor {

	// 切面
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("invoke before");
        Object result = methodProxy.invokeSuper(o, objects);
        System.out.println("cglib proxy return result : " + result);
        System.out.println("invoke after");
        return result;
    }
}

// 测试
public class InterceptorTest {

    public static void main(String[] args) {
        Enhancer enhancer = new Enhancer();
        // 要代理的类
        enhancer.setSuperclass(OrderServiceImpl.class);
        // 使用哪一个实现了MyMethodInterceptor的类
        enhancer.setCallback(new MyMethodInterceptor());
        // 创建代理
        OrderServiceImpl orderService = (OrderServiceImpl) enhancer.create();
        orderService.say();
    }
}


输出结果如下:
Connected to the target VM, address: '127.0.0.1:62510', transport: 'socket'
invoke before
cglib proxy return result : order service impl
invoke after
Disconnected from the target VM, address: '127.0.0.1:62510', transport: 'socket'
  1. jdk实现InvocationHandler类 重写invoke实现切面,cglib实现MethodInterceptor类 重写intercept实现切面
  2. jdk代理是生成代理对象 会调用invoke方法,cglib利用ASM技术 直接编译到class内
  3. jdk代理是作用在interface上, cglib代理可以是任意类 final除外

3. AOP底层ProxyFactory

    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjrt</artifactId>
        <version>1.9.6</version>
    </dependency>
public class MyAdvisor implements PointcutAdvisor {

    @Override
    public Pointcut getPointcut() {
        NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut();
        methodPointcut.addMethodName("say");
        return methodPointcut;
    }

    @Override
    public Advice getAdvice() {
        MethodBeforeAdvice methodBeforeAdvice = new MethodBeforeAdvice() {
            @Override
            public void before(Method method, Object[] args, Object target) throws Throwable {
                System.out.println("执行方法前"+method.getName());
            }
        };

        return methodBeforeAdvice;
    }

    @Override
    public boolean isPerInstance() {
        return false;
    }
}

3.1 从上述代码,可以看出Advisor与Advice的关系,我们可以理解Advice是一个建议,Advisor是一个统筹,Pointcut是一个切点,这个方法就是针对代理的对象的say方法进行before切面。
在Spring中,Advice分为:
前置Advice:MethodBeforeAdvice
后置Advice:AfterReturningAdvice
环绕Advice:MethodInterceptor
异常Advice:ThrowsAdvice

public static void main(String[] args) {
	// ProxyFactory spring的代理工厂
	ProxyFactory proxyFactory = new ProxyFactory();
	// 目标对象
	proxyFactory.setTarget(new OrderServiceImpl());
	// 选填 实现的接口
	proxyFactory.setInterfaces(OrderService.class);
	// 添加Advisor 加载切面逻辑
	proxyFactory.addAdvisor(new MyAdvisor());
	// 获得代理对象
	OrderService orderService = (OrderService) proxyFactory.getProxy();
	orderService.say();
    }

3.2 从这三个创建代理形式可以看出来,创建代理要具备三个条件。(1. 目标对象 2.切面逻辑 3.根据1和2创建代理对象)
3.3 接下来 着重看一下proxyFactory.getProxy()方法的实现 也是到底选择JDK动态代理 还是CGLIB代理的实现

public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
	// proxyFactory可以设置isOptimize属性
	// EnableAspectJAutoProxy注解的proxyTargetClass属性
	// Class<?>[] ifcs = config.getProxiedInterfaces();
	// (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])))
	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.");
		}
		// 一般来讲target都是一个对象 很少进这个方法
		if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
			return new JdkDynamicAopProxy(config);
		}
		// 如果不干预设置ProxyFactory属性 ProxyFactory没有添加interfaces
		return new ObjenesisCglibAopProxy(config);
	}
	else {
		// 如果不干预设置ProxyFactory属性 ProxyFactory添加了interfaces
		return new JdkDynamicAopProxy(config);
	}
}

4. SpringAOP 实例化后postProcessAfterInitialization后置处理器:第一个记载Advisor相关逻辑 着重看第二个

在这里插入图片描述

@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
	if (bean != null) {
		Object cacheKey = getCacheKey(bean.getClass(), beanName);
		if (this.earlyProxyReferences.remove(cacheKey) != bean) {
			// 最重要的方法 wrapIfNecessary 如果需要AOP 则AOP
			return wrapIfNecessary(bean, beanName, cacheKey);
		}
	}
	return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
	// 实例化前生成aop代理的 直接return
	if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
		return bean;
	}
	if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
		return bean;
	}
	// 一些特殊类 直接return
	if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
		this.advisedBeans.put(cacheKey, Boolean.FALSE);
		return bean;
	}

	// Create proxy if we have advice.
	// 寻找符合条件的候选Advistor
	Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
	if (specificInterceptors != DO_NOT_PROXY) {
		this.advisedBeans.put(cacheKey, Boolean.TRUE);
		// 创建AOP
		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;
}
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
			@Nullable Object[] specificInterceptors, TargetSource targetSource) {

	if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
		AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
	}

	// 底层创建代理 就是ProxyFactory
	ProxyFactory proxyFactory = new ProxyFactory();
	proxyFactory.copyFrom(this);

	if (!proxyFactory.isProxyTargetClass()) {
		if (shouldProxyTargetClass(beanClass, beanName)) {
			proxyFactory.setProxyTargetClass(true);
		}
		else {
			// setInterfaces
			evaluateProxyInterfaces(beanClass, proxyFactory);
		}
	}

	// 构建Advisor 切面逻辑
	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());
}

5. @Aspect 对应的一些切面注解

5.1 @Before对应的是AspectJMethodBeforeAdvice,直接实现MethodBeforeAdvice,在进行动态代理时会把AspectJMethodBeforeAdvice转成MethodBeforeAdviceInterceptor,也就转变成了MethodBeforeAdviceInterceptor
a. 先执行advice对应的方法
b. 再执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
5.2 @After对应的是AspectJAfterAdvice,直接实现了MethodInterceptor
a. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
b. 再执行advice对应的方法
5.3 @Around对应的是AspectJAroundAdvice,直接实现了MethodInterceptor
a. 直接执行advice对应的方法
5.4 @AfterThrowing对应的是AspectJAfterThrowingAdvice,直接实现了MethodInterceptor
a. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
b. 如果上面抛了Throwable,那么则会执行advice对应的方法
5.5 @AfterReturning对应的是AspectJAfterReturningAdvice,实现了AfterReturningAdvice,在进行动态代理时会把AspectJAfterReturningAdvice转成AfterReturningAdviceInterceptor,也就转变成了MethodInterceptor
a. 先执行MethodInvocation的proceed(),会执行下一个Interceptor,如果没有下一个Interceptor了,会执行target对应的方法
b. 执行上面的方法后得到最终的方法的返回值
c. 再执行Advice对应的方法

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值