Aop简述

        AOP( 面向切面编程 )是一种思想,它的目的就是在不修改源代码的基础上,对原有功能进行增强。

SpringAOP是对AOP思想的一种实现,Spring底层同时支持jdk和cglib动态代理。

Spring会根据被代理的类是否有接口自动选择代理方式:

  • 如果有接口,就采用jdk动态代理

  • 如果没接口,就采用cglib的方式

jdk动态代理

// 代理工厂实现(AOP)
public class JDKProxyFactory {
    // 获得代理对象的方法
    public static Object getProxy(final Class clazz){
        Object proxy = Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Logger logger = new Logger();
                Object obj = null;
                try {
                    // 前置增强
                    logger.m1();
                    // 告诉虚拟机要调用method方法
                    obj = method.invoke(clazz.newInstance(), args);
                    // 后置增强
                    logger.m2();
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.m3();
                }
                return obj; // 真实方法的返回值
            }
        });
        return proxy; // 返回代理对象
    }
}

cglib动态代理

public class CglibProxyFactory {
    public static Object getProxy(final Class clazz){
        // 创建一个代理工具类
        Enhancer enhancer = new Enhancer();
        // 根据父类创建子类对象
        enhancer.setSuperclass(clazz);
        // 调用代理对象的方法
        enhancer.setCallback(new InvocationHandler() {
            @Override
            /**
             * 参数1:代理对象本身的引用(一般不用)
             * 参数2:代理对象调的方法
             * 参数3:代理对象调的方法的参数
             */
            public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
                Object invoke = null;
                Logger logger = new Logger();
                try {
                    // 前置增强
                    logger.m1();

                    // 告诉虚拟机要调用method方法
                    invoke = method.invoke(clazz.newInstance(), objects);

                    // 后置增强
                    logger.m2();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                    logger.m3();
                }
                return invoke;  // 返回方法执行的返回值
            }
        });

        // 生成代理对象并返回
        Object proxy = enhancer.create();
        return proxy;

    }
}

实现步骤

导入依赖
<!--切点表达式解析坐标-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.7</version>
        </dependency>
写增强类
@Component
@Aspect // 切面注解
public class Logger {
    
    // 切点方式一  execution(返回值类型 方法路径)   * 代表一个或多个位置    .. 代表0个或多个位置
    // @Pointcut("execution(java.util.List com.itheima.service.impl.*.*(..))")
    
    // 切点方式二  @annotation(自定义注解全限定类名)
    @Pointcut("@annotation(com.itheima.annotation.LogAnno)")
    public void pt(){}
	
    // 四大通知
    
	// 前置通知(before):增强方法在切点运行之前执行
	// 返回后通知(after-returning):增强方法在某切点正常完成后执行的通知,不包括抛出异常的情况
	// 异常后通知(after-throwing):增强方法在某切点抛出异常退出时执行的通知
	// 后置通知(after):增强方法在某切点退出的时候执行的通知(不论是正常返回还是异常退出)
        
try{
	前置通知(before)
	//切点执行位置
	返回后通知(after-returning)
}catch(Execption e){
	异常后通知(after-throwing)
}finally{
	后置通知(after)
}
        
    // @Before("pt()")
    // public void m1() {
    //     System.out.println("方法执行之前,执行了" + LocalDateTime.now());
    // }
    //
    // @After("pt()")
    // public void m2() {
    //     System.out.println("方法运行结束,执行了" + LocalDateTime.now());
    // }
    //
    // @AfterReturning("pt()")
    // public void m4() {
    //     System.out.println("方法返回结果后,执行了" + LocalDateTime.now());
    // }
    //
    // @AfterThrowing("pt()")
    // public void m3() {
    //     System.out.println("方法出现异常,执行了" + LocalDateTime.now());
    // }

    @Around("pt()")
    public Object m5(ProceedingJoinPoint pjp){
        Object object = null;
        try {
            System.out.println("方法执行前,执行了");

            object = pjp.proceed();

            System.out.println("方法执行后,执行了(return后)");
        } catch (Throwable e) {
            e.printStackTrace();
            System.out.println("方法异常了,执行了");
        } finally {
            System.out.println("方法运行到最后完全结束了,执行了");
            return object;
        }
    }
}
配置类注解
@ComponentScan("com.itheima")
@EnableAspectJAutoProxy // 激活切面自动代理
public class SpringConfig {
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值