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

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

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

<?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> 

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

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注解标注的切入类

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】------");
  }
} 

最后是客户端测试类

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文件

<?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*(..))
 --> 

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

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中所指定的切入类

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】------");
  }
}

最后是客户端测试类

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");
  }
}

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

(0)

相关推荐

  • java基于spring注解AOP的异常处理的方法

    一.前言 项目刚刚开发的时候,并没有做好充足的准备.开发到一定程度的时候才会想到还有一些问题没有解决.就比如今天我要说的一个问题:异常的处理.写程序的时候一般都会通过try...catch...finally对异常进行处理,但是我们真的能在写程序的时候处理掉所有可能发生的异常吗? 以及发生异常的时候执行什么逻辑,返回什么提示信息,跳转到什么页面,这些都是要考虑到的. 二.基于@ControllerAdvice(加强的控制器)的异常处理 @ControllerAdvice注解内部使用@Except

  • 关于spring中aop的注解实现方法实例详解

    前言 在之前的一篇文章中我们讲到spring的xml实现,这里我们讲讲使用注解如何实现aop呢.前面已经讲过aop的简单理解了,这里就不在赘述了.话不多说,来一起看看详细的介绍: 注解方式实现aop我们主要分为如下几个步骤: 1.在切面类(为切点服务的类)前用@Aspect注释修饰,声明为一个切面类. 2.用@Pointcut注释声明一个切点,目的是为了告诉切面,谁是它的服务对象.(此注释修饰的方法的方法体为空,不需要写功能比如 public void say(){};就可以了,方法名可以被候命

  • 使用Spring的注解方式实现AOP实例

    spring对AOP的实现提供了很好的支持.下面我们就使用Spring的注解来完成AOP做一个例子. 首先,为了使用Spring的AOP注解功能,必须导入如下几个包.aspectjrt.jar,aspectjweaver.jar,cglib-nodep.jar.然后我们写一个接口 package com.bird.service; public interface PersonServer { public void save(String name); public void update(S

  • 详解Spring Aop实例之AspectJ注解配置

    上篇<Spring Aop实例之xml配置>中,讲解了xml配置方式,今天来说说AspectJ注解方式去配置spring aop. 依旧采用的jdk代理,接口和实现类代码请参考上篇博文.主要是将Aspect类分享一下: package com.tgb.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Aft

  • Spring AOP 基于注解详解及实例代码

    Spring AOP  基于注解详解及实例代码 1.启用spring对@AspectJ注解的支持: <beans xmlns:aop="http://www.springframework.org/schema/aop"...> <!--启动支持--> <aop:aspectj-autoproxy /> </beans> 也可以配置AnnotationAwareAspectJAutoProxyCreator Bean来启动Spring对@

  • Spring AOP 自定义注解的实现代码

    1.在Maven中加入以下以依赖: <!-- Spring AOP + AspectJ by shipengzhi --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>3.0.6.RELEASE</version> </dependency> <

  • spring中AOP 注解开发示例详解

    一.简介 AOP主要包含了通知.切点和连接点等术语,介绍如下: 通知(advice) 通知定义了切面是什么以及何时调用,何时调用包含以下几种 Before 在方法被调用之前调用通知 After 在方法完成之后调用通知,无论方法执行是否成功 After-returning 在方法成功执行之后调用通知 After-throwing 在方法抛出异常后调用通知 Around 通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为 切点(PointCut) 通知定义了切面的什么和何时,切

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

    本文演示的是Spring中使用AspectJ注解和XML配置两种方式实现AOP 下面是使用AspectJ注解实现AOP的Java Project 首先是位于classpath下的applicationContext.xml文件 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmln

  • 在Spring Boot中加载XML配置的完整步骤

    开篇 在SpringBoot中我们通常都是基于注解来开发的,实话说其实这个功能比较鸡肋,但是,SpringBoot中还是能做到的.所以用不用是一回事,会不会又是另外一回事. 涛锅锅在个人能力能掌握的范围之内,一般是会得越多越好,都是细小的积累,发生质的改变,所以今天和小伙伴们一起分享一下. 实践 1.首先我们新建一个SpringBoot Project ,工程名为 xml 2.添加web依赖,点击Finish完成构建 3.我们新建一个类 SayHello 不做任何配置 package org.t

  • mybatis中注解与xml配置的对应关系和对比分析

    注解与xml配置的对应关系 mybatis中注解就是简单不需要写配置文件,适合简单的数据处理,理解起来比较容易,不动态生成SQL时候可以用用. 需要绑定,有些时候不如配置文件,配置文件扩展强. 选择合适的方式应用在合适的场景,注解主要应用于sql语句比较简单容易理解的情况下可读性高:生成动态sql时用xml配置文件要更简洁,扩展性强 常用的注解和xml的对应关系 @CacheNamespace 类 <cache> @CacheNamespaceRef 类 <cacheRef> @R

  • Spring中的事务操作、注解及XML配置详解

    事务 事务全称叫数据库事务,是数据库并发控制时的基本单位,它是一个操作集合,这些操作要么不执行,要么都执行,不可分割.例如我们的转账这个业务,就需要进行数据库事务的处理. 转账中至少会涉及到两条 SQL 语句: update Acoount set balance = balance - money where id = 'A'; update Acoount set balance = balance + money where id = 'B' 上面这两条 SQL 就可以要看成是一个事务,必

  • Spring Aop之AspectJ注解配置实现日志管理的方法

    最近项目要做一个日志功能,我用Spring Aop的注解方式来实现. 创建日志注解 package com.wyj.annotation; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lan

  • Spring如何通过注解存储和读取对象详解

    目录 1. 创建Spring 项目 1.1 创建⼀个 Maven 项⽬ 1.2 添加 Spring 框架支持 1.3 添加启动类 2. 存储 Bean 对象 2.1 创建Bean 2.2 配置 spring-config.xml 3. 获取并使用 Bean 对象 3.1 创建Sprign 上下文 3.2  获取指定的 Bean 对象 3.3 使用Bean 4.总结 5.配置扫描路径 6.添加注解存储 6.1 @Controller(控制器存储) 6.2 @Service (服务器存储) 6.3

  • Spring五大类注解读取存储Bean对象的方法

    目录 前情提要 配置spring-config文件 类注解和方法注解 @Controller(控制器存储) @Service(服务存储) @Configuration(配置存储) @Repository(仓库存储) @Component(组件存储) 5大类注解联系 Spring给Bean命名规则 方法注解@Bean 重命名Bean 获取Bean对象(对象装配) 属性注入 构造方法注入 Setter注入 三种注入方式对比 注入同一类型多个Bean对象 前情提要 我们上节内容学习了如何创建\注册\读

  • Spring的注解配置与XML配置之间的比较

    注释配置相对于 XML 配置具有很多的优势:它可以充分利用 Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作.如使用 JPA 注释配置 ORM 映射时,我们就不需要指定 PO 的属性名.类型等信息,如果关系表字段和 PO 属性名.类型都一致,您甚至无需编写任务属性映射信息--因为这些信息都可以通过 Java 反射机制获取. 注释和 Java 代码位于一个文件中,而 XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和 Java 代码放在一起,

  • 如何完成spring的最小化XML配置

    一.自动装配 1.四种类型的自动装配 类型 解释 xml 配置 byName 根据 Bean 的 name 或者 id <bean id="bean" class="-" autowire="byName"/> ByType 根据 Bean 类型自动装配 <bean id="bean" class="-" autowire="byType"/> contructo

随机推荐