欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring之AOP学习小结

程序员文章站 2022-05-24 23:43:57
...
在学习aop之前先来解释一下aop一些概念
[list]
[*]Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。
[*]Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。
[*]Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,
[*]Aspect:实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。
[*]Target:被通知的对象。
[*]Proxy:将通知应用到目标对象后创建的对象
[*]Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。
[/list]

spring对AOP的支持有以下4种情况:
[list]
[*]经典的基于代理的aop(各版本spring)
[*]@AspectJ注解驱动的切面(spring2.0后)
[*]纯pojo切面(spring2.0后)
[*]注入式AspectJ切面(各版本spring)
[/list]

ITarget.java
package com.myspring.aop;

public interface ITarget {
public void execute() throws TargetException;
}


TargetImpl.java
package com.myspring.aop;

public class TargetImpl implements ITarget {

public TargetImpl() {
}

public void execute() throws TargetException {
System.out.println("main...");
}
}


创建通知
Advice .java
package com.myspring.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;

public class Advice implements MethodBeforeAdvice,
AfterReturningAdvice, ThrowsAdvice {

public Advice() {}

public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("传统经典aop的before...");
}

public void afterReturning(Object rtn, Method method,
Object[] args, Object target) throws Throwable {
System.out.println("传统经典aop的afterReturning...");
}

public void afterThrowing(Throwable throwable) {
System.out.println("传统经典aop的afterThrowing...");
}

public void afterThrowing(Method method, Object[] args, Object target,
Throwable throwable) {
System.out.println("传统经典aop的afterThrowing2...");
}

}


TargetException .java
package com.myspring.aop;

@SuppressWarnings("serial")
public class TargetException extends RuntimeException {
public TargetException() {}

public TargetException(String message) {
super(message);
}
}


使用自动代理@AspectJ切面时,需要先注册一个切面AspectAdvice.java
package com.myspring.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect//声明切面
public class AspectAdvice {

@Pointcut("execution(* *.execute(..))")//定义切点,匹配规则为(返回类型 返回类.方法(参数设置)
public void todo(){}

@Before("todo()")
public void before() {
System.out.println("自动代理@AspectJ切面before...");
}

@AfterReturning("todo()")
public void afterReturning() {
System.out.println("自动代理@AspectJ切面afterReturning...");
}

@AfterThrowing("todo()")
public void afterThrowing() {
System.out.println("自动代理@AspectJ切面afterThrowing...");
}

}

AdviceBean.java
package com.myspring.aop;

public class AdviceBean {

public void before() {
System.out.println("纯POJO切面before...");
}

public void afterReturning() {
System.out.println("纯POJO切面afterReturning...");
}

public void afterThrowing() {
System.out.println("纯POJO切面afterThrowing...");
}
}



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:p="http://www.springframework.org/schema/p"
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.0.xsd">

<!-- 当定义一个纯粹的POJO切面时,创建此Bean -->
<bean id="adviceBean" class="com.myspring.aop.AdviceBean"></bean>
<!-- 利用spring AOP的配置元素定义一个通知 -->
<aop:config>
<!-- 引用刚才定义的一个纯粹的POJO切面Bean -->
<aop:aspect ref="adviceBean">
<!-- 定义一个命名切点,必点切点定义的重复,expression用于配置匹配规则,(返回类型 返回类.方法(参数设置) -->
<aop:pointcut id="todo" expression="execution(* com.myspring.aop.TargetImpl.execute(..))" />
<!-- 方法前通知 -->
<aop:before method="before" pointcut-ref="todo" />
<aop:after-returning method="afterReturning" pointcut-ref="todo" />
<aop:after-throwing method="afterThrowing" pointcut-ref="todo"/>
</aop:aspect>
</aop:config>

<!-- ************************************** -->
<bean id="aspectAdvice" class="com.myspring.aop.AspectAdvice"></bean>
<!-- 当使用自动代理@AspectJ切面时,需要定义自动配置元素,在原来的xml文件的beans中加入xmlns:aop="http://www.springframework.org/schema/aop" http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd,具体位置如上 -->
<aop:aspectj-autoprox />

<!-- ************************************** -->
<!-- 以下为传统的aop代理 -->
<!-- 定义一个bean -->
<bean id="target" class="com.myspring.aop.TargetImpl">
</bean>

<!-- 定义一个通知bean -->
<bean id="advice" class="com.myspring.aop.Advice">
</bean>

<!-- 正则表达式切入点 -->
<bean id="jdkRegexpAdvisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pattern" value=".*execute" />
</bean>

<!-- AspectJ切点 -->
<bean id="aspectjPointcut" class="org.springframework.aop.aspectj.AspectJExpressionPointcutAdvisor">
<property name="advice" ref="advice" /> <property name="expression"
value="execution(* *.execute(..))" /> </bean>
<!-- 使用ProxyFactoryBean工厂,用于生成一个代理,把一个或多个拦截者(和通知者)应用到Bean -->
<bean id="myAop" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="target" />
<property name="proxyInterfaces" value="com.myspring.aop.ITarget" />
<property name="interceptorNames" value="jdkRegexpAdvisor" />
</bean>

<!-- 创建自动代理,会自动检查通知者的切点是否匹配bean的方法,并且使用通知的代理来替换这个bean定义 -->
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" />
</beans>


TestSpringAop.java
package com.myspring.aop;

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

public class TestSpringAop {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//使用经典的aop
ITarget target = (ITarget) ctx.getBean("myAop");
//使用自动代理,可以直接调用目标对象
ITarget autotarget = (ITarget) ctx.getBean("target");
target.execute();
}
}