依赖
动态代理
请参考http://blog.csdn.net/keysilence1/article/details/52495207
实现
基于注入方式
步骤一,创建切面类
package com.silence.spring.aop.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
public class AspectExecute {
private void allMethod() {
}
public void beforeMethod(JoinPoint joinPoint) {
System.out.println("before method");
}
public void afterMethod(JoinPoint joinPoint) {
System.out.println("after method");
}
public void afterReturningMethod(JoinPoint joinPoint, Object result) {
System.out.println("after returning method");
}
public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) {
System.out.println("after throwing method");
}
//Around可以完全控制方法的执行时机,和屏蔽方法的执行
public void arroundMethod(ProceedingJoinPoint pjd) {
System.out.println("arround method start");
try {
//此处需显示的执行目标方法,否则目标方法将不执行
Object result = pjd.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("arround method end");
}
}
步骤二,创建被切对象接口
package com.silence.spring.aop.bussiness;
public interface Human {
void say();
}
步骤三,创建被切对象实现
package com.silence.spring.aop.bussiness.impl;
import com.silence.spring.aop.bussiness.Human;
public class Man implements Human {
public void say() {
System.out.println("i am a man");
}
}
步骤四,创建配置文件,命名为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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--切面,就是切到之后要执行的动作的集合-->
<bean id = "aspectExecute" class="com.silence.spring.aop.aspect.AspectExecute"/>
<bean id = "man" class="com.silence.spring.aop.bussiness.impl.Man"/>
<aop:config proxy-target-class="true">
<aop:aspect ref="aspectExecute">
<!-- 切入点,具体在哪些类或者方法上执行切面,可以定义多个切入点 -->
<aop:pointcut id="say" expression="execution(* com.silence.spring.aop.bussiness.Human.say(..))"/>
<!-- 通知,具体切到之后要执行的动作集合的哪些方法 -->
<aop:after method="afterMethod" pointcut-ref="say"/>
<aop:after-returning method="afterReturningMethod" pointcut-ref="say" returning="result"/>
<aop:after-throwing method="afterThrowingMethod" pointcut-ref="say" throwing="ex"/>
<aop:around method="arroundMethod" pointcut-ref="say"/>
<aop:before method="beforeMethod" pointcut-ref="say"/>
</aop:aspect>
</aop:config>
</beans>
步骤五,创建测试类
package com.silence.spring.aop.test;
import com.silence.spring.aop.bussiness.Human;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Human man = (Human) ctx.getBean("man");
man.say();
}
}
步骤六,输出测试结果,证实切面成功
before method
i am a man
after method
after returning method
基于动态代理
步骤一,创建切面类
package com.silence.spring.aop.aspect;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
@Aspect
public class AspectExecute {
@Pointcut("execution(* com.silence.spring.aop.bussiness.*.*(..))")
private void allMethod() {
}
@Before("allMethod()")
public void beforeMethod(JoinPoint joinPoint) {
System.out.println("before method");
}
@After("allMethod()")
public void afterMethod(JoinPoint joinPoint) {
System.out.println("after method");
}
@AfterReturning(value="allMethod()", returning="result")
public void afterReturningMethod(JoinPoint joinPoint, Object result) {
System.out.println("after returning method");
}
@AfterThrowing(value="allMethod()", throwing = "ex")
public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) {
System.out.println("after throwing method");
}
@Around("allMethod()")
public void arroundMethod(ProceedingJoinPoint pjd) {
System.out.println("arround method start");
try {
//此处需显示的执行目标方法,否则目标方法将不执行
Object result = pjd.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
System.out.println("arround method end");
}
}
步骤二,创建被切对象接口
package com.silence.spring.aop.bussiness;
public interface Human {
void say();
}
步骤三,创建被切对象实现
package com.silence.spring.aop.bussiness.impl;
import com.silence.spring.aop.bussiness.Human;
public class Man implements Human {
public void say() {
System.out.println("i am a man");
}
}
步骤四,创建配置文件,命名为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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--切面,就是切到之后要执行的动作的集合-->
<bean id = "aspectExecute" class="com.silence.spring.aop.aspect.AspectExecute"/>
<bean id = "man" class="com.silence.spring.aop.bussiness.impl.Man"/>
<aop:aspectj-autoproxy proxy-target-class="true"/>
</beans>
步骤五,创建测试类
package com.silence.spring.aop.test;
import com.silence.spring.aop.bussiness.Human;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
Human man = (Human) ctx.getBean("man");
man.say();
}
}
步骤六,输出测试结果,证实切面成功
arround method start
before method
i am a man
arround method end
after method
after returning method
总结
相比较而言,动态代理的方式简化了配置,并使代码变得更清晰,推荐使用。