12.21 Spring集成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命名空间
定义切面<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
启动类:
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(){
    ...
}
/* 表示在某个方法之后调用 */
 
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号