服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服务器之家 - 编程语言 - JAVA教程 - Spring使用AspectJ注解和XML配置实现AOP

Spring使用AspectJ注解和XML配置实现AOP

2020-06-24 11:53玄玉 JAVA教程

这篇文章主要介绍了Spring使用AspectJ注解和XML配置实现AOP的相关资料,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP

下面是使用AspectJ注解实现AOP的Java Project
首先是位于classpath下的applicationContext.xml文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
   
  <!-- 启用AspectJ对Annotation的支持 -->    
  <aop:aspectj-autoproxy/>
       
  <bean id="userManager" class="com.jadyer.annotation.UserManagerImpl"/>
   
  <bean id="securityHandler" class="com.jadyer.annotation.SecurityHandler"/>
</beans>

然后是服务层接口以及实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
package com.jadyer.annotation;
public interface UserManager {
  public void addUser(String username, String password);
  public void delUser(int userId);
  public String findUserById(int userId);
  public void modifyUser(int userId, String username, String password);
}
 
/**
 * 上面的UserManager是服务层的接口
 * 下面的UserManagerImpl是服务层接口的实现类
 */
 
package com.jadyer.annotation;
 
public class UserManagerImpl implements UserManager {
  public void addUser(String username, String password) {
    System.out.println("------UserManagerImpl.addUser() is invoked------");
  }
 
  public void delUser(int userId) {
    System.out.println("------UserManagerImpl.delUser() is invoked------");
  }
 
  public String findUserById(int userId) {
    System.out.println("------UserManagerImpl.findUserById() is invoked------");
    return "铁面生";
  }
 
  public void modifyUser(int userId, String username, String password) {
    System.out.println("------UserManagerImpl.modifyUser() is invoked------");
  }
}

接下来是使用AspectJ注解标注的切入类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
package com.jadyer.annotation;
 
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
 
@Aspect
public class SecurityHandler {
  /**
   * 定义Pointcut
   * @see Pointcut的名称为addAddMethod(),此方法没有返回值和参数
   * @see 该方法就是一个标识,不进行调用
   */
  @Pointcut("execution(* add*(..))") //匹配所有以add开头的方法
  private void addAddMethod(){};
   
  /**
   * 定义Advice
   * @see 表示我们的Advice应用到哪些Pointcut订阅的Joinpoint上
   */
  //@Before("addAddMethod()")
  @After("addAddMethod()")
  private void checkSecurity() {
    System.out.println("------【checkSecurity is invoked】------");
  }    
}

最后是客户端测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.jadyer.annotation;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * Spring对AOP的支持:采用Annotation方式
 * @see -------------------------------------------------------------------------------------
 * @see Spring提供的AOP功能还是很强大的,支持可配置,它的默认实现使用的就是JDK动态代理
 * @see 使用Spring的AOP不需要继承相关的东西,也不需要实现接口
 * @see 但有个前提条件:由于是JDK动态代理,所以若想生成代理,该类就必须得实现一个接口才行
 * @see 如果该类没有implements接口的话,仍去使用Spring的默认AOP实现时,那么就会出错
 * @see 通常需要生成代理的类都是服务层的类,所以通常都会抽一个接口出来。即养成面向接口编程的习惯
 * @see -------------------------------------------------------------------------------------
 * @see 采用Annotation方式完成AOP示例的基本步骤,如下
 * @see 1、Spring2.0的依赖包配置。新增Annotation支持
 * @see   * SPRING_HOME//dist//spring.jar
 * @see   * SPRING_HOME//lib//log4j//log4j-1.2.14.jar
 * @see   * SPRING_HOME//lib//jakarta-commons//commons-logging.jar
 * @see   * SPRING_HOME//lib//aspectj//*.jar
 * @see 2、将横切性关注点模块化,建立SecurityHandler.java
 * @see 3、采用注解指定SecurityHandler为Aspect
 * @see 4、采用注解定义Advice和Pointcut
 * @see 5、启用AspectJ对Annotation的支持,并且将目标类和Aspect类配置到IoC容器中
 * @see 6、开发客户端
 * @see -------------------------------------------------------------------------------------
 */
public class Client {
  public static void main(String[] args) {
    ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext.xml");
    UserManager userManager = (UserManager)factory.getBean("userManager");
    userManager.addUser("张起灵", "02200059");
  }
}

下面是使用XML配置文件实现AOP的Java Project
首先是位于src根目录中的applicationContext-cglib.xml文件

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<?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"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="
      http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
      http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
      http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
       
  <!-- 强制使用CGLIB代理 -->
  <!-- <aop:aspectj-autoproxy proxy-target-class="true"/> -->
   
  <bean id="userManager" class="com.jadyer.cglib.UserManagerImpl"/>
   
  <bean id="securityHandler" class="com.jadyer.cglib.SecurityHandler"/>
   
  <aop:config>
    <aop:aspect id="securityAspect" ref="securityHandler"
      <aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
      <aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
    </aop:aspect>
  </aop:config>
</beans>
 
<!-- 
匹配add开头的所有的方法
execution(* add*(..))
 
匹配com.jadyer.servcices.impl包下的所有的类的所有的方法
execution(* com.jadyer.servcices.impl.*.*(..))
 
匹配com.jadyer.servcices.impl包下的add或者del开头的所有的方法
execution(* com.jadyer.servcices.impl.*.add*(..)) || execution(* com.jadyer.servcices.impl.*.del*(..))
 -->

然后是服务层接口以及实现类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package com.jadyer.cglib;
public interface UserManager {
  public void addUser(String username, String password);
  public void delUser(int userId);
  public String findUserById(int userId);
  public void modifyUser(int userId, String username, String password);
}
 
/**
 * 上面的UserManager是服务层接口
 * 下面的UserManagerImpl是服务层接口的实现类
 */
 
package com.jadyer.cglib;
 
public class UserManagerImpl { 
//implements UserManager {
  public void addUser(String username, String password) {
    System.out.println("------UserManagerImpl.addUser() is invoked------");
  }
 
  public void delUser(int userId) {
    System.out.println("------UserManagerImpl.delUser() is invoked------");
  }
 
  public String findUserById(int userId) {
    System.out.println("------UserManagerImpl.findUserById() is invoked------");
    return "张三";
  }
 
  public void modifyUser(int userId, String username, String password) {
    System.out.println("------UserManagerImpl.modifyUser() is invoked------");
  }
}

接着是在applicationContext-cglib.xml中所指定的切入类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package com.jadyer.cglib;
 
import org.aspectj.lang.JoinPoint;
 
/**
 * 将客户调用信息传递到该Advice中
 * @see 可以在Advice中添加一个JoinPoint参数,取得客户端调用的方法名称及参数值
 * @see 以后纯粹使用AOP去写类似这样东西的情况比较少,我们主要使用Spring提供的事务
 * @see 关于这个,知道即可。下面是示例代码
 */
public class SecurityHandler {
  private void checkSecurity(JoinPoint joinPoint) {
    for (int i=0; i<joinPoint.getArgs().length; i++) {
      System.out.println(joinPoint.getArgs()[i]); //获取客户端调用的方法的参数值
    }
    System.out.println(joinPoint.getSignature().getName()); //获取客户端调用的方法名称
    System.out.println("------【checkSecurity is invoked】------");
  }
}

最后是客户端测试类

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.jadyer.cglib;
 
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
 
/**
 * @see --------------------------------------------------------------------------------------------------
 * @see JDK动态代理和CGLIB代理的差别
 * @see 1..JDK动态代理对实现了接口的类进行代理
 * @see 2..CGLIB代理可以对类代理,主要对指定的类生成一个子类。由于是继承,所以目标类最好不要使用final声明
 * @see --------------------------------------------------------------------------------------------------
 * @see 代理方式的选择
 * @see 1..如果目标对象实现了接口,默认情况下会采用JDK动态代理实现AOP,亦可强制使用CGLIB生成代理实现AOP
 * @see 2..如果目标对象未实现接口,那么必须引入CGLIB,这时Spring会在JDK动态代理和CGLIB代理之间自动切换
 * @see 3..比较鼓励业务对象是针对接口编程的,所以鼓励使用JDK动态代理。因为我们所代理的目标,一般都是业务对象
 * @see --------------------------------------------------------------------------------------------------
 * @see 使用CGLIG代理的步骤
 * @see 1..新增CGLIB库:SPRING_HOME//lib//cglib//*.jar
 * @see 2..新增配置标签,强制使用CGLIB代理<aop:aspectj-autoproxy proxy-target-class="true"/>
 * @see --------------------------------------------------------------------------------------------------
 */
public class Client {
  public static void main(String[] args) {
    ApplicationContext factory = new ClassPathXmlApplicationContext("applicationContext-cglib.xml");
     
    //当UserManagerImpl实现了UserManager接口的情况下,这时Spring会自动使用JDK动态代理
    //如果项目已经引入cglib库,并在配置文件中强制使用CGLIB代理,此时Spring才会使用CGLIB代理
    //UserManager userManager = (UserManager)factory.getBean("userManager");
     
    //由于此时的UserManagerImpl并没有实现UserManager接口,所以接收类型就不能再使用UserManager接口
    //并且项目中已经引入了cglib库,尽管配置文件中没有强制使用CGLIB代理,但Spring会自动使用CGLIB代理   
    UserManagerImpl userManager = (UserManagerImpl)factory.getBean("userManager");
     
    userManager.addUser("吴三省", "02200059");
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。

延伸 · 阅读

精彩推荐
  • JAVA教程解决dubbo错误ip及ip乱入问题的方法

    解决dubbo错误ip及ip乱入问题的方法

    今天小编就为大家分享一篇关于解决dubbo错误ip及ip乱入问题的方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随...

    双斜杠少年5992019-06-24
  • JAVA教程Java 线程池详解及实例代码

    Java 线程池详解及实例代码

    这篇文章主要介绍了Java 线程池的相关资料,并符实例代码,帮助大家学习参考,需要的朋友可以参考下 ...

    f2yy2042020-06-16
  • JAVA教程Mybatis传递多个参数进行SQL查询的用法

    Mybatis传递多个参数进行SQL查询的用法

    本文给大家介绍Mybatis传递多个参数进行SQL查询的用法的相关知识,本文还给大家介绍了mybatis通过Map传递多个参数和JavaBean传递多个参数,本文介绍的非常详...

    zifangsky1962020-05-23
  • JAVA教程java异常机制分析

    java异常机制分析

    这篇文章主要介绍了java异常机制,包括异常机制的捕获、抛出及常见的异常机制总结,需要的朋友可以参考下 ...

    shichen20141992019-11-28
  • JAVA教程java数组输出的实例代码

    java数组输出的实例代码

    这篇文章主要介绍了java数组输出的实例代码,有需要的朋友可以参考一下 ...

    java代码网3202019-10-26
  • JAVA教程java读取csv文件和写csv示例分享

    java读取csv文件和写csv示例分享

    这篇文章主要介绍了JAVA对CSV格式文本数据处理后再保存成新CSV格式文本的模板,可以学习到java读取csv文件和写csv的方法,需要的朋友可以参考下 ...

    java技术网2242019-11-14
  • JAVA教程深入理解Java 对象和类

    深入理解Java 对象和类

    下面小编就为大家带来一篇深入理解Java 对象和类。小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧 ...

    jingxian3442020-04-28
  • JAVA教程详解Java中使用externds关键字继承类的用法

    详解Java中使用externds关键字继承类的用法

    子类使用extends继承父类是Java面向对象编程中的基础知识,这里我们就来详解Java中使用externds关键字继承类的用法,需要的朋友可以参考下 ...

    DBOY3772020-05-25