Spring5.0.4 AOP 使用AspectJ方式自动代理注解(@EnableAspectJAutoProxy)

本文使用Maven建立的项目
pom.xml 文件内容


<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.0modelVersion>

    <groupId>com.dyhgroupId>
    <artifactId>TestDemoartifactId>
    <version>1.0-SNAPSHOTversion>
    <dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-coreartifactId>
            <version>5.0.4.RELEASEversion>
        dependency>
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-aopartifactId>
            <version>4.3.9.RELEASEversion>
        dependency>

        
        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjrtartifactId>
            <version>1.6.11version>
        dependency>

        <dependency>
            <groupId>org.aspectjgroupId>
            <artifactId>aspectjweaverartifactId>
            <version>1.6.11version>
        dependency>
        
        <dependency>
            <groupId>cglibgroupId>
            <artifactId>cglibartifactId>
            <version>2.1version>
        dependency>
    dependencies>
project>

下面会用到AspectJ的几种通知注解的:

  1. @Before: 前置通知, 在方法执行之前执行
  2. @After: 后置通知, 在方法执行之后执行
  3. @AfterRunning:返回通知, 在方法成功执行返回结果之后执行
  4. @AfterThrowing: 异常通知, 在方法抛出异常之后
  5. @Around: 环绕通知,围绕着方法执行

有2种方法实现aop功能,本文使用的是javaconfig配置类注解实现,另一种是基于xml配置文件
接口类

package com.dyh.ioc.base;

public interface Weapon {

    public void attack();
}

实体类

package com.dyh.ioc.base;

import org.springframework.stereotype.Component;
@Component
public class Knifie implements Weapon {
    public void attack() {
        System.out.println("C");
    }
}

实现类

package com.dyh.ioc.base;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class Knight {
    private String name;
    private Weapon weapon;

    public Knight() {

    }
    public Knight(String name,Weapon weapon){
        this.name = name;
        this.weapon = weapon;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Weapon getWeapon() {
        return weapon;
    }
    //自动注入
    @Autowired
    //用于指定注入Bean的名称
    @Qualifier("knifie")
    public void setWeapon(Weapon weapon) {
        this.weapon = weapon;
    }

    public void fight(){
        System.out.println("start ......");
        System.out.println(name);
        weapon.attack();
    }
}

JavaConfig类

package com.dyh.ioc.base;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;


//即使用jdk默认代理模式,AspectJ代理模式是CGLIB代理模式
//如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
//如果目标对象实现了接口,可以强制使用CGLIB实现AOP (此例子我们就是强制使用cglib实现aop)
//如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

//用于定义配置类,可替换xml配置文件
@Configuration
//开启AspectJ 自动代理模式,如果不填proxyTargetClass=true,默认为false,
@EnableAspectJAutoProxy(proxyTargetClass=true)
//扫描注入类
@ComponentScan(basePackages = "com.dyh.ioc.*")
@Component
@Aspect
public class AopAspectConfiguration {
    //声明切入点
    //第一个*表示 方法  返回值(例如public int)
    //第二个* 表示方法的全限定名(即包名+类名)
    //perform表示目标方法参数括号两个.表示任意类型参数
    //方法表达式以“*”号开始,表明了我们不关心方法返回值的类型。然后,我们指定了全限定类名和方法名。对于方法参数列表,
    //我们使用两个点号(..)表明切点要选择任意的perform()方法,无论该方法的入参是什么
    //execution表示执行的时候触发
    @Pointcut("execution(* *(..))")
    public void point(){
        //该方法就是一个标识方法,为pointcut提供一个依附的地方
    }

    @Before("point()")
    public void before(){
        System.out.println("Before");
    }
    @After("point()")
    public void after(){
        System.out.println("After");
    }
}

测试类

package com.dyh.ioc.base;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args){
        AnnotationConfigApplicationContext  applicationContext = new AnnotationConfigApplicationContext(AopAspectConfiguration.class);
        Knight knight = applicationContext.getBean("knight",Knight.class);
        knight.setName("123");
        knight.fight();
    }
}

最终执行结果

E:\java\jdk1.8.0_162\bin\java -javaagent:E:\IDEA\lib\idea_rt.jar=65304:E:\IDEA\bin -Dfile.encoding=UTF-8 -classpath E:\java\jdk1.8.0_162\jre\lib\charsets.jar;E:\java\jdk1.8.0_162\jre\lib\deploy.jar;E:\java\jdk1.8.0_162\jre\lib\ext\access-bridge-64.jar;E:\java\jdk1.8.0_162\jre\lib\ext\cldrdata.jar;E:\java\jdk1.8.0_162\jre\lib\ext\dnsns.jar;E:\java\jdk1.8.0_162\jre\lib\ext\jaccess.jar;E:\java\jdk1.8.0_162\jre\lib\ext\jfxrt.jar;E:\java\jdk1.8.0_162\jre\lib\ext\localedata.jar;E:\java\jdk1.8.0_162\jre\lib\ext\nashorn.jar;E:\java\jdk1.8.0_162\jre\lib\ext\sunec.jar;E:\java\jdk1.8.0_162\jre\lib\ext\sunjce_provider.jar;E:\java\jdk1.8.0_162\jre\lib\ext\sunmscapi.jar;E:\java\jdk1.8.0_162\jre\lib\ext\sunpkcs11.jar;E:\java\jdk1.8.0_162\jre\lib\ext\zipfs.jar;E:\java\jdk1.8.0_162\jre\lib\javaws.jar;E:\java\jdk1.8.0_162\jre\lib\jce.jar;E:\java\jdk1.8.0_162\jre\lib\jfr.jar;E:\java\jdk1.8.0_162\jre\lib\jfxswt.jar;E:\java\jdk1.8.0_162\jre\lib\jsse.jar;E:\java\jdk1.8.0_162\jre\lib\management-agent.jar;E:\java\jdk1.8.0_162\jre\lib\plugin.jar;E:\java\jdk1.8.0_162\jre\lib\resources.jar;E:\java\jdk1.8.0_162\jre\lib\rt.jar;E:\WorkSpaces\TestDemo\target\classes;E:\apache-maven-3.5.2\repo\org\springframework\spring-context\5.0.4.RELEASE\spring-context-5.0.4.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\springframework\spring-beans\5.0.4.RELEASE\spring-beans-5.0.4.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\springframework\spring-expression\5.0.4.RELEASE\spring-expression-5.0.4.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\springframework\spring-core\5.0.4.RELEASE\spring-core-5.0.4.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\springframework\spring-jcl\5.0.4.RELEASE\spring-jcl-5.0.4.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\springframework\spring-aop\4.3.9.RELEASE\spring-aop-4.3.9.RELEASE.jar;E:\apache-maven-3.5.2\repo\org\aspectj\aspectjrt\1.6.11\aspectjrt-1.6.11.jar;E:\apache-maven-3.5.2\repo\org\aspectj\aspectjweaver\1.6.11\aspectjweaver-1.6.11.jar;E:\apache-maven-3.5.2\repo\cglib\cglib\2.1\cglib-2.1.jar;E:\apache-maven-3.5.2\repo\asm\asm\1.5.3\asm-1.5.3.jar;E:\apache-maven-3.5.2\repo\asm\asm-util\1.3.4\asm-util-1.3.4.jar;E:\apache-maven-3.5.2\repo\aspectwerkz\aspectwerkz-core\0.8.1\aspectwerkz-core-0.8.1.jar com.dyh.ioc.base.Test
二月 27, 2018 5:36:19 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh
信息: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@1ed6993a: startup date [Tue Feb 27 17:36:19 CST 2018]; root of context hierarchy
Before
After
Before
After
Before
start ......
123
Before
C
After
After

Process finished with exit code 0

初学spring,如有错误敬请留言斧正

你可能感兴趣的:(spring)