AOP中xlm配置和注解配置

本文深入解析面向切面编程(AOP)的概念及其在Spring框架中的应用,介绍AOP如何通过预编译和动态代理实现程序功能的统一维护,探讨JDK代理与CGLIB代理的区别,并提供基于XML和注解的AOP配置示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

概念:Aspect Oriented Programming 面向切面编程

面向切面编程时一种改编成思想。就是通过预编译和运行期的动态代理,实现程序功能的统一维护。spring是对这个思想的实现。
动态代理:简而言之就是在不修改源代码的情况下,对其中的方法进行增强,实现调用者和实现者的解耦。常用的动态代理有:

  1. JDK代理:基于接口的动态代理技术
  2. cglib代理:基于父类的动态代理技术

对一些概念理解:

  1. Target(目标对象)要增强的对象
  2. Proxy(代理)增强后的对象。
  3. Joinpoint(连接点)要增强的方法
  4. Pointcut(切点)被增强的方法
  5. Advice(通知)增强方法
  6. Aspect(切面)通知+切点。就是增强后的方法。
  7. Weaving(织入)通知和切点相结合的过程。创建增强的代理对象的过程。

基于JDK

这个代理基于Java的反射机制实现的。主要涉及到java.lang.reflect包中的Proxy和InvocationHandler。
底层代码简单写了一下

public class Proxy动态增强 {
    public static void main(String[] args) {
        /*
         * jdk的动态增强,基于接口。
         */
        //创建要增强的对象
        final Target target = new Target ();
        //创建增强类,存的是增强的功能
        final Aspect aspect = new Aspect();
        //使用动态代理将要增强的对象和功能组织到一块儿
        Egg ss = (Egg) Proxy.newProxyInstance(
                target.getClass().getClassLoader(),//目标对象的类加载器
                target.getClass().getInterfaces(),//目标对象相同接口字节码对象数组
                new InvocationHandler(){
                    //调用代理对象的方法,实际执行的都是invoke方法。
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                //调用增强功能
                aspect.before();
                //执行目标原有方法
                method.invoke(target ,args);
                //调用增强功能
                aspect.after();
                return null;
            }
        });
        ss.fight();
    }
}
浅谈一下为什么用final修饰

在jdk1.8以后就不用了,之前需要。
main方法执行开始,进栈内存,成员变量进栈内存,常量进常量池。new对象的时候,对象在对内存。栈内存存储的是new出来的对象的地址值。在堆内存的对象引用被赋值的成员变量时,是不可以的。就相当于从堆内存找栈内存的数据。而在方法执行完毕后,成员变量随着方法的结束而消失,到那时堆内存的对象暂时不会消失。所以强大编码软件就会报错。被final修饰的变量为常量,存在于常量池中。常量池中的数据随着程序的结束而消失,所以堆内存的对象在寻找它需要的变量时,可以直接从常量池中寻找。所以用final修饰。
1.8以后,jdk在编译.class文件的时候就会加上final。所以不用。

1 基于xml

  1. 导入坐标spring-context和context依赖的aop

     <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>5.0.5.RELEASE</version>
     </dependency>
     <!-- aspectj的织入 -->
     <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.8.13</version>
     </dependency>
    
  2. 导入aop的命名空间

     <beans xmlns="http://www.springframework.org/schema/beans"
            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
            xmlns:context="http://www.springframework.org/schema/context"
            xmlns:aop="http://www.springframework.org/schema/aop"
            xsi:schemaLocation="
             http://www.springframework.org/schema/context
             http://www.springframework.org/schema/context/spring-context.xsd
             http://www.springframework.org/schema/aop
             http://www.springframework.org/schema/aop/spring-aop.xsd
             http://www.springframework.org/schema/beans
             http://www.springframework.org/schema/beans/spring-beans.xsd">
    

导入命名空间

  1. 在配置文件中配置织入关系

     <!--目标对象-->
        <bean id="target" class="cn.itcast.jdkProxyXml.Target"/>
        <!--切面对象-->
        <bean id="myAspect" class="cn.itcast.jdkProxyXml.MyAspect"/>
        <!--配置织入:告诉spring哪些方法(切点)需要哪些增强(前置、后置... ... )-->
        <aop:config>
            <!--声明切面类-->
            <aop:aspect ref="myAspect">
                <aop:pointcut id="myPoint" expression="execution(public void cn.itcast.jdkProxyXml.Target.save())"/>
                <!--生成切面:切点+通知-->
                <aop:after method="after" pointcut-ref="myPoint"/>
                <aop:around method="around" pointcut-ref="myPoint"/>
                <aop:before method="before" pointcut-ref="myPoint"/>
            </aop:aspect>
        </aop:config>
    </beans>
    

配置织入
黄色箭头为提取切点表达式。
蓝色为通知类型
红色为切点表达式的写法
切点表达式的写法
通知的类型

浅谈为什么用aspectjweaver这个jar包

spring中已经有aop的jar包了,为什么还要引入aspectjweaver这个。简单的说就是后面这个比spring自己坐的jar包要好。
如果仅仅用xlm的配置方法,原生的aop就可以了,但是要使用注解,就的引入aspectjweaver这个jar包。

2 基于注解

在配置文件中配置组键扫描和自动代理。

<!--组件扫描-->
<context:component-scan base-package="com.itheima.aop"/>

<!--aop的自动代理-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

配置组件扫描和自动代理
注解配置与xml的大同小异
在这里插入图片描述
切点表达式的抽取

@@Component("myAspect")
@Aspect
public class MyAspect {
    @Before("MyAspect.myPoint()")
    public void before(){
        System.out.println("前置代码增强.....");
    }
    @Pointcut("execution(* com.itheima.aop.*.*(..))")
    public void myPoint(){}
}

声明切面类
声明切面类

基于cglib

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河西彭于晏

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值