spring aop

本文没有去探寻源码,只是根据现象去推理一下:

1 定义切面类:

package main.daoImpl;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class LogAnnotationAspect {
	
	@Pointcut("execution(* main.daoImpl.*.*(..))")
	public void allMethod() {}

	@Before("allMethod()")
	public void before(JoinPoint jp) {
		System.out.println("Args:" + jp.getArgs());
		System.out.println("Kind:" + jp.getKind());
		System.out.println("Signature:" + jp.getSignature());
		System.out.println("Target:" + jp.getTarget());
		System.out.println("this:" + jp.getThis());
		System.out.println("正在进行权限校验!before...");
		System.out.println(jp.getSignature().getName());
		if (jp.getSignature().getName().equals("login")) {
		}
	}
	
	@After("allMethod()")
	public void after() {
		System.out.println("结束调用!after...");
	}
	
	@Around("allMethod()")
	public void around(ProceedingJoinPoint pjp) throws Throwable {
		System.out.println("环绕! around...");
		pjp.proceed();
	}
	
	@AfterReturning(pointcut="allMethod()", returning="rvt")
	public void afterReturning(Object rvt) {
		System.out.println("rrrrrrrrrrrrrrrrrrrrrrrr     " + rvt + "    rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr");
	}
	
	@AfterThrowing("allMethod()")
	public void afterThrow() {
		System.out.println("after throwing...");
	}
	
}

 2 目标类

   (1)目标类不实现接口:

     

package main.daoImpl;

import main.dao.TestDao;

public class TestDaoImpl {

	public String test() throws Exception {
		System.out.println("test main...");
		return "test data!";
	}
	

   测试代码:

  

	@Test
	public void test() {
		try {
			TestDaoImpl testDaoImpl = (TestDaoImpl)context.getBean("testDaoImpl");
			System.out.println("current class: " + testDaoImpl.getClass().getName());
			System.out.println("parent class or interface : " + testDaoImpl.getClass().getSuperclass().getName());
			System.out.println("is aop proxy: " + AopUtils.isAopProxy(testDaoImpl));
			System.out.println("is cglib proxy: " + AopUtils.isCglibProxy(testDaoImpl));
			System.out.println("is jdk proxy: " + AopUtils.isJdkDynamicProxy(testDaoImpl));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			
		}
	}

    测试结果:

   current class: main.daoImpl.TestDaoImpl$$EnhancerByCGLIB$$a6cb1969
   parent class or interface : main.daoImpl.TestDaoImpl
  is aop proxy: true
  is cglib proxy: true
  is jdk proxy: false

  从获取的testDaoImpl的class名称为:main.daoImpl.TestDaoImpl$$EnhancerByCGLIB$$a6cb1969,熟悉cglib动态代理的应该知道,这类名称符合cglib动态代理生成类的命名,而且testDaoImpl父类的名称为:main.daoImpl.TestDaoImpl,也就是testDaoImpl继承了类main.daoImpl.TestDaoImpl,此恰恰符合cglib动态代理的特征;所以当目标类没有实现接口时,spring aop使用cglib动态代理生成一个代理类,把切面类

中配置的通知织入到动态代理类内,代理类调用方法时,就会触发通知。

 

    (2)目标类实现接口:

package main.daoImpl;

import main.dao.TestDao;

public class TestDaoImpl implements TestDao {

	public String test() throws Exception {
		System.out.println("test main...");
		return "test data!";
	}
	
}

    切面类和上面一致,测试代码为:

	@Test
	public void test() {
		try {
			TestDao testDaoImpl = (TestDao)context.getBean("testDaoImpl");
			System.out.println("current class: " + testDaoImpl.getClass().getName());
			System.out.println("parent class or interface : " + testDaoImpl.getClass().getSuperclass().getName());
			System.out.println("is aop proxy: " + AopUtils.isAopProxy(testDaoImpl));
			System.out.println("is cglib proxy: " + AopUtils.isCglibProxy(testDaoImpl));
			System.out.println("is jdk proxy: " + AopUtils.isJdkDynamicProxy(testDaoImpl));
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			
		}
	}

 测试结果:

current class: $Proxy13
parent class or interface : java.lang.reflect.Proxy
is aop proxy: true
is cglib proxy: false
is jdk proxy: true

testDaoImpl类名为$Proxy13, 继承了 java.lang.reflect.Proxy,由此可知当目标类实现接口的时候,spring aop 使用jdk的动态代理生成动态代理类把通知织入到动态代理类内

 

从上面的代码可知,spring aop的总体逻辑为,根据目标类是否实现接口来选择使用jdk还是使用cglib来生成代理类,把通知中的逻辑织入到代理类中

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值