12.21 Spring集成AspectJ

12.21Spring集成AspectJ

在新版本的Spring框架中使用AspectJ开发AOP

AspectJ是什么

概念:

基于Java语言的AOP框架,扩展了Java语言

使用AspectJ开发AOP的方式

  • 基于XML的声明式AspectJ

  • 基于Annotation的声明式AspectJ

基于AspectJ XML开发Spring AOP

具体是指:

通过Spring配置文件的方式来定义切面、切入点、通知。

具体实现:

所有的切面和通知必须定义在<aop:config>元素中

步骤:

  • 导入Spring aop命名空间

  • 定义切面

  • 定义切入点

  • 定义通知

导入Spring aop命名空间
<?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-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
  ...
</beans>
定义切面<aop:aspect>

作用:

把定义好的Bean转换成切面Bean。所以使用该元素需要先定义一个普通Spring Bean

示例:

<aop:config>
   <aop:aspect id="myAspect" ref="aBean">
      ...
   </aop:aspect>
</aop:config>
<!--
id用来定义该切面唯一表示名称
ref用于引用普通的Spring Bean
-->
定义切入点<aop:pointcut>

作用:

定义一个切入点

  • 作为<aop:config>元素的子元素---->表示该切入点是全局切入点

  • 作为<aop:aspect>元素的子元素--->表示该切入点只对当前切面有效

示例:

<aop:config>
   <aop:pointcut id="myPointCut"
       expression="execution(* com.junkingboy.service.*.*(..))"/>
</aop:config>
<!--
id用于指定切入点的唯一标识名称
execution指定切入点关联的切入点表达式
-->

execution格式:

execution(modifiers-pattern returning-type-pattern declaring-type-pattern name-pattern(param-pattern)throws-pattern)
  • returning-type-pattern、name-pattern、param-pattern 是必须的,其它参数为可选项。

  • modifiers-pattern:指定修饰符,如 private、public。

  • returning-type-pattern:指定返回值类型,*表示可以为任何返回值。如果返回值为对象,则需指定全路径的类名。

  • declaring-type-pattern:指定方法的包名。

  • name-pattern:指定方法名,*代表所有,set* 代表以 set 开头的所有方法。

  • param-pattern:指定方法参数(声明的类型),(..)代表所有参数,(*)代表一个参数,(*,String)代表第一个参数可以为任何值,第二个为 String 类型的值。

  • throws-pattern:指定抛出的异常类型。

定义通知

具体可定义五种类型的advice

<aop:aspect id="" ref="">
<!-- 前置通知 -->
   <aop:before pointcut-ref="" method="" />
   
<!-- 后置通知 -->
   <aop:after-returning pointcut-ref="" method="" />
<!-- 环绕通知 -->
   <aop:around pointcut-ref="" method="" />
<!-- 异常通知 -->
   <aop:after-throwing pointcut-ref="" method="" />
<!-- 最终通知 -->
   <aop:after pointcut-ref="" method="" />
  ...
</aop:aspect>

理解:

本质上就是通过xml对各个接口、类、Bean对象实现调用而非代码上的强制调用。

定义loggin类:

public class Logging {
   /**
    * 前置通知
    */
   public void beforeAdvice() {
       System.out.println("前置通知");
  }
   /**
    * 后置通知
    */
   public void afterAdvice() {
       System.out.println("后置通知");
  }
   /**
    * 返回后通知
    */
   public void afterReturningAdvice(Object retVal) {
       System.out.println("返回值为:" + retVal.toString());
  }
   /**
    * 抛出异常通知
    */
   public void afterThrowingAdvice(IllegalArgumentException ex) {
       System.out.println("这里的异常为:" + ex.toString());
  }
}

ORM的对象:

package net.biancheng;
public class Man {
   private String name;
   private int age;
   public String getName() {
       return name;
  }
   public void setName(String name) {
       this.name = name;
  }
   public int getAge() {
       return age;
  }
   public void setAge(int age) {
       this.age = age;
  }
   public void throwException() {
       System.out.println("抛出异常");
       throw new IllegalArgumentException();
  }
}

Beanxml

<?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-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">

<!-- 使用config标签声明下面是配置 -->
   <aop:config>
  <aop:aspect id="log" ref="logging">
      <aop:pointcut id="selectAll" expression="excution()" />
      <aop:before pointcut-ref="selectAll" method="beforeAdvice" />
      <aop:after pointcut-ref="selectAll" method="afterAdvice" />
      <aop:after-returning pointcut-ref="selectAll" returning="retVal" method="afterReturningAdvice" />
      <aop:after-throwing pointcut-ref="selectAll" throwing="" method="afterThrowingAdvice" />
       </aop:aspect>
       
       <!-- 下面定义bean -->
   <bean id="man" class="net.biancheng.Man">
       <property name="name" value="bianchengbang" />
       <property name="age" value="12" />
   </bean>
       
   <bean id="logging" class="net.biancheng.Logging" />
       
   </aop:config>

启动类:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MainApp {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Man man = (Man) context.getBean("man");
man.getName();
man.getAge();
man.throwException();
}
}

AspectJ基于注解开发AOP

为了防止xml文件过于臃肿,AspectJ 框架为 AOP 开发提供了一套注解。AspectJ 允许使用注解定义切面、切入点和增强处理,Spring 框架可以根据这些注解生成 AOP 代理。

Annotation注解介绍:

名称说明
@Aspect 用于定义一个切面。
@Pointcut 用于定义一个切入点。
@Before 用于定义前置通知,相当于 BeforeAdvice。
@AfterReturning 用于定义后置通知,相当于 AfterReturningAdvice。
@Around 用于定义环绕通知,相当于MethodInterceptor。
@AfterThrowing 用于定义抛出通知,相当于ThrowAdvice。
@After 用于定义最终final通知,不管是否异常,该通知都会执行。
@DeclareParents 用于定义引介通知,相当于IntroductionInterceptor(不要求掌握)。

@AspectJ注解的两种方法:

使用@Configuration和@EnableAspectJAutoProxy注解:

@Configuration
@EnableAspectJAutoProxy
public class Appconfig{

}

基于xml配置:

<aop:aspectj-autoproxy>
定义切面@Aspect

使用Aspect注解:

import org.aspectj.lang.annotation.Aspect;

@Aspect
public class AspectModule {
}

xml中配置:

<bean id = "myAspect" class = "类路径">
...
</bean>
定义切入点@Pointcut

使用Aspect注解*

// 要求:方法必须是private,返回值类型为void,名称自定义,没有参数
@Pointcut("execution(*包名..*.*(..))")
private void myPointCut() {
}

xml中配置:

<aop:pointcut expression="execution(*包名..*.*(..))"  id="myPointCut"/>
定义通知advice

上面说到的五种类型,以before作为示例:

@Before("方法名")
public void beforeAdvice(){
...
}
/* 表示在某个方法之后调用 */

 

posted @ 2022-01-18 19:06  俊king  阅读(185)  评论(0)    收藏  举报