Spring基于XML的AOP开发&&基于注解的AOP开发

基于XML的AOP开发

  1. pom文件

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>org.example</groupId>
        <artifactId>spring_aop_xml</artifactId>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <maven.compiler.source>11</maven.compiler.source>
            <maven.compiler.target>11</maven.compiler.target>
        </properties>
        <dependencies>
            <!--导入spring的context坐标,context依赖aop-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.1.5.RELEASE</version>
            </dependency>
            <!-- aspectj的织入(切点表达式需要用到该jar包) -->
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
                <version>1.8.13</version>
            </dependency>
            <!--spring整合junit-->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-test</artifactId>
                <version>5.1.5.RELEASE</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
            </dependency>
        </dependencies>
    </project>
    
  2. 创建目标接口和目标实现类

    package com.code.service;
    
    public interface AccountService {
        
        //目标方法:(切入点:要进行拦截增强的方法)
        public void transfer();
    }
    
    package com.code.service.impl;
    
    import com.code.service.AccountService;
    
    public class AccountServiceImpl implements AccountService {
    
        /*
            目标方法:(切入点:要进行拦截增强的方法)
        */
        @Override
        public void transfer() {
    
            System.out.println("转账方法执行了....");
            //int i = 1/0;
        }
    }
    
  3. 创建通知类

    public class MyAdvice {
    	public void before() {
    		System.out.println("前置通知...");
    	}
    }
    
  4. Spring配置文件,将目标类和通知类对象创建权交给spring

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:aop="http://www.springframework.org/schema/aop"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
    		http://www.springframework.org/schema/beans/spring-beans.xsd
    		http://www.springframework.org/schema/aop
    		http://www.springframework.org/schema/aop/spring-aop.xsd">
    
    
        <!--目标类交给IOC容器-->
        <bean id="accountServcie" class="com.code.service.impl.AccountServiceImpl"></bean>
    
        <!--通知类交给IOC容器-->
        <bean id="myAdvice" class="com.code.advice.MyAdvice"></bean>
    
    
    
        <!--
        execution([修饰符] 返回值类型 包名.类名.方法名(参数))
        execution(public void com.code.service.impl.AccountServiceImpl.transfer(java.lang.String))
    
        - 访问修饰符可以省略
        execution(void com.code.service.impl.AccountServiceImpl.transfer(java.lang.String))
    
        - 返回值类型、包名、类名、方法名可以使用星号 * 代替,代表任意
        execution(* *.*.*.*.*.*())
    
        - 包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类
        execution(* *..*.*())
    
        - 参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表
        execution(* *..*.*(..))
        -->
    
        <!--AOP配置-->
        <aop:config>
            <!--抽取的切点表达式-->
            <aop:pointcut id="accountService" expression="execution(* com.code.service.impl.AccountServiceImpl.*(..))"/>
    
            <!--配置切面:切入点+通知-->
            <aop:aspect ref="myAdvice">
                <aop:before method="before" pointcut-ref="accountService"/>
                <aop:after-returning method="afterReturning" pointcut-ref="accountService"/>
                <aop:after-throwing method="afterThrowing" pointcut-ref="accountService"/>
                <aop:after method="after" pointcut-ref="accountService"/>
                <aop:around method="around" pointcut-ref="accountService"/>
    
            </aop:aspect>
    
        </aop:config>
        
    
    </beans>
    
  5. 切点表达式抽取:当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替pointcut 属性来引用抽取后的切点表达式

    <aop:config>
    	<!--抽取的切点表达式-->
    	<aop:pointcut id="myPointcut" expression="execution(* com.code.service..*.*(..))"> </aop:pointcut>
    	<aop:aspect ref="myAdvice">
    		<aop:before method="before" pointcut-ref="myPointcut"></aop:before>
    	</aop:aspect>
    </aop:config>
    
  6. 通知的配置语法:<aop:通知类型 method=“通知类中方法名” pointcut=“切点表达式"></aop:通知类型>

    名称标签说明
    前置通知aop:before用于配置前置通知。指定增强的方法在切入点方法之前执行
    后置通知aop:afterReturning用于配置后置通知。指定增强的方法在切入点方法之后执行
    异常通知aop:afterThrowing用于配置异常通知。指定增强的方法出现异常后执行
    最终通知aop:after用于配置最终通知。无论切入点方法执行时是否有异常,都会执行
    环绕通知aop:around用于配置环绕通知。开发者可以手动控制增强代码在什么时候执行

基于注解的AOP开发

  1. pom文件

    <dependencies>
        <!--导入spring的context坐标,context依赖aop-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <!-- aspectj的织入 -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
        <!--spring整合junit-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>
    
  2. 创建目标接口和目标实现类

    public interface AccountService {
    	public void transfer();
    }
    
    public class AccountServiceImpl implements AccountService {
    	@Override
    	public void transfer() {
    		System.out.println("转账业务...");
    	}
    }
    
  3. 创建通知类:

    public class MyAdvice {
    	public void before() {
    		System.out.println("前置通知...");
    	}
    }
    
  4. 将目标类和通知类对象创建权交给spring

    @Service
    public class AccountServiceImpl implements AccountService {}
    
    @Component
    public class MyAdvice {}
    
  5. 在通知类中使用注解配置织入关系,升级为切面类

    @Component
    @Aspect
    public class MyAdvice {
    	@Pointcut("execution(* com.code..*.*(..))")
    	public void myPoint(){}
    	
    	@Before("MyAdvice.myPoint()")
    	public void before() {
    	System.out.println("前置通知...");
    	}
    }
    
  6. 在配置文件中开启组件扫描和 AOP 的自动代理

    <!--组件扫描-->
    <context:component-scan base-package="com.code"/>
    <!--aop的自动代理-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
  7. 通知类型:通知的配置语法:@通知注解(“切点表达式")

    名称标签说明
    前置通知@Before用于配置前置通知。指定增强的方法在切入点方法之前执行
    后置通知@AfterReturning用于配置后置通知。指定增强的方法在切入点方法之后执行
    异常通知@AfterThrowing用于配置异常通知。指定增强的方法出现异常后执行
    最终通知@After用于配置最终通知。无论切入点方法执行时是否有异常,都会
    执行环绕通知@Around用于配置环绕通知。开发者可以手动控制增强代码在什么时候执行
  8. 当前四个通知组合在一起时,执行顺序:@Before -> @After -> @AfterReturning(如果有异常:@AfterThrowing)

  9. 纯注解配置

    package com.code.config;
    
    
    import org.springframework.context.annotation.ComponentScan;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableAspectJAutoProxy;
    
    @Configuration
    @ComponentScan("com.code")
    @EnableAspectJAutoProxy //开启AOP的自动代理 替代了<aop:aspectj-autoproxy>
    public class SpringConfig {
    }
     
    
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值