AOP(Aspect Oriented Programming)称为面向切面编程思想,它是对于OOP(面向对象)思想的扩展和补充。它主要用来解决一些系统层面上的问题,比如系统日志、权限、声明式事务;在不改变系统原有逻辑的基础上,增加一些额外的功能。
通过实现日志的的例子实现AOP编程。
首先创建业务类接口和具体实现类(实现日志添加)
1、业务类接口
public interface IOrderService {
void createNewOrder(int maney);
}
2、具体实现类
public class OrderServiceImpl implements IOrderService {
@Override
public void createNewOrder(int maney) {
System.out.println("【业务层】创建新订单,金额为"+maney);
}
}
3、日志类
/**
* MethodBeforeAdvice:前置通知接口
* AfterReturningAdvice:后置通知接口
* MethodInterceptor: 环绕通知
*/
public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice {
/**
*
* @param method 目标方法
* @param objects 方法参数列表
* @param o 目标对象
* @throws Throwable
*/
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("【前置通知】"+method.getName()+"方法执行,在"+new Date()+"开始执行");
}
/**
*
* @param o 方法返回值
* @param method 目标方法
* @param objects 方法参数列表
* @param o1 目标对象
* @throws Throwable
*/
@Override
public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {
System.out.println("【后置通知】"+method.getName()+"方法执行,在"+new Date()+"执行结束");
}
}
4、导入相关依赖(除spring核心依赖依赖外还需要导入
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-aopartifactId>
<version>5.2.1.RELEASEversion>
dependency>
5、spring-config.xml的配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orderServiceTargetBean" class="com.apesource.service.impl.OrderServiceImpl"/>
<bean id="logAdviceBean" class="com.apesource.advice.LogAdvice"/>
<bean id="orderServiceBean" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.apesource.service.IOrderServicevalue>
property>
<property name="target">
<ref bean="orderServiceTargetBean"/>
property>
<property name="interceptorNames">
<value>logAdviceBeanvalue>
property>
bean>
beans>
6、测试类
public class Test01 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
IOrderService orderService = (IOrderService) context.getBean("orderServiceBean");
orderService.creatNewOrder(10);
}
}
1、业务类接口与实现类相同,实现方法性能的测试,性能测试类如下
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
/**
* MethodInterceptor:环绕通知接口
*/
public class PerformanceAdvice implements MethodInterceptor {
/**
*
* @param methodInvocation 目标方法
* @return 目标方法返回值
* @throws Throwable
*/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("【环绕通知前置】方法性能检测开始!");
double begin = System.currentTimeMillis();
Object resultValue = methodInvocation.proceed();
double end = System.currentTimeMillis();
System.out.println("【环绕通知前置】方法性能检测结束!共耗时:"+(end+begin));
return resultValue;
}
}
2、spring-config1.xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="orderServiceBean" class="com.apesource.service.impl.OrderServiceImpl"/>
<bean id="performanceAdviceBean" class="com.apesource.advice.PerformanceAdvice"/>
<bean id="createMethodPointcut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<property name="pattern" value=".*create.*"/>
bean>
<bean id="performanceAdvisorBean" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<property name="pointcut" ref="createMethodPointcut"/>
<property name="advice" ref="performanceAdviceBean"/>
bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*ServiceBeanvalue>
list>
property>
<property name="interceptorNames">
<list>
<value>LogAdviceBeanvalue>
<value>performanceAdvisorBeanvalue>
list>
property>
bean>
beans>
3、测试类
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config1.xml");
IOrderService orderService = (IOrderService) context.getBean("orderServiceBean");
orderService.createNewOrder(10);
}
1、业务类接口
public interface IUserService {
int createNewUser();
void loginOut();
}
2、实现类
@Service("userServiceBean")
public class UserServiceImpl implements IUserService {
@Override
public int createNewUser() {
// int a = 12/0;// 用于测试异常通知
System.out.println("【业务层】创建新的用户");
return 1001;
}
@Override
public void loginOut() {
System.out.println("【业务层】用户退出登录");
}
}
3、切面类:
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
/**
* 使用Aspectj实现切面
*/
public class LogAspect {
/**
* 实现前置通知
*/
public void beforeAspect(JoinPoint joinPoint){
System.out.println("【前置通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("【前置通知】结束。。。。。");
}
/**
* 实现后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知
* @param joinPoint
* @param returnVal 返回值
*/
public void afterAspect(JoinPoint joinPoint, Object returnVal){
System.out.println("【后置有返回值通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("目标方法返回值"+returnVal);
System.out.println("【后置有返回值通知】结束。。。。。");
}
/**
* 后置通知
*/
public void afterAdvice(JoinPoint joinPoint){
System.out.println("【后置无返回值通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("【后置无返回值通知】结束。。。。。");
}
/**
* 异常通知:方法出现异常时,执行该通知
* @param joinPoint
* @param e 异常对象
*/
public void exceptionAdvice(JoinPoint joinPoint, Exception e){
System.out.println("【异常通知】开始。。。。。");
System.out.println("异常通知"+e.getMessage());
System.out.println("【异常通知】结束。。。。。");
}
/**
* 环绕通知
* @param joinpoint
* @return 目标方法返回值
* @throws Throwable
*/
public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("。。。。。【环绕通知前置】。。。。。");
Object returnVal = joinpoint.proceed();// 执行目标方法
System.out.println("。。。。。【环绕通知后置】。。。。。");
return returnVal;
}
}
4、spring-config2.xml配置文件
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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="userServiceBean" class="com.apesource.service.impl.UserServiceImpl"/>
<bean class="com.apesource.aspectj.LogAspect" id="logAspectBean"/>
<aop:config>
<aop:aspect ref="logAspectBean">
<aop:pointcut id="serviceMethodPointcut" expression="execution(* com.apesource.service.impl.*.create*(..) )"/>
<aop:before method="beforeAspect" pointcut-ref="serviceMethodPointcut"/>
<aop:after-returning returning="returnVal" method="afterAspect" pointcut-ref="serviceMethodPointcut"/>
<aop:after method="afterAdvice" pointcut-ref="serviceMethodPointcut"/>
<aop:after-throwing method="exceptionAdvice" throwing="e" pointcut-ref="serviceMethodPointcut"/>
<aop:around method="aroundAdvice" pointcut-ref="serviceMethodPointcut"/>
aop:aspect>
aop:config>
beans>
5、测试类
public class Test03 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config2.xml");
IUserService userService = (IUserService) context.getBean("userServiceBean");
userService.createNewUser();
userService.loginOut();
}
}
1、实体类使用userServiceImpl
2、切面类
/**
* 使用Aspectj实现切面(注解实现)
*/
@Aspect//声明当前类为Aspect切面,并交给Spring容器管理
@Component
public class LogAnnotationAspect {
private static final String POINTCUT_EXPRESSION = "execution(* com.apesource.service.impl.*.create*(..) )";// 切入点
/**
* 实现前置通知
*/
@Before(POINTCUT_EXPRESSION)
public void beforeAspect(JoinPoint joinPoint){
System.out.println("【前置通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("【前置通知】结束。。。。。");
}
/**
* 实现后置通知:方法正常执行后,有返回值,执行该后置通知;如果该方法执行出现异常,则不执行该后置通知
* @param joinPoint
* @param returnVal 返回值
*/
@AfterReturning(value =POINTCUT_EXPRESSION,returning = "returnVal")
public void afterAspect(JoinPoint joinPoint, Object returnVal){
System.out.println("【后置有返回值通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("目标方法返回值"+returnVal);
System.out.println("【后置有返回值通知】结束。。。。。");
}
/**
* 后置通知
*/
@After(POINTCUT_EXPRESSION)
public void afterAdvice(JoinPoint joinPoint){
System.out.println("【后置无返回值通知】开始。。。。。");
System.out.println("目标对象"+joinPoint.getTarget());
System.out.println("目标方法"+joinPoint.getSignature().getName());
System.out.println("目标方法参数"+joinPoint.getArgs());
System.out.println("【后置无返回值通知】结束。。。。。");
}
/**
* 异常通知:方法出现异常时,执行该通知
* @param joinPoint
* @param e 异常对象
*/
@AfterThrowing(value =POINTCUT_EXPRESSION, throwing = "e")
public void exceptionAdvice(JoinPoint joinPoint, Exception e){
System.out.println("【异常通知】开始。。。。。");
//System.out.println("异常通知"+e.getMessage());
System.out.println("【异常通知】结束。。。。。");
}
/**
* 环绕通知
* @param joinpoint
* @return 目标方法返回值
* @throws Throwable
*/
@Around(POINTCUT_EXPRESSION)
public Object aroundAdvice(ProceedingJoinPoint joinpoint) throws Throwable {
System.out.println("。。。。。【环绕通知前置】。。。。。");
Object returnVal = joinpoint.proceed();// 执行目标方法
System.out.println("。。。。。【环绕通知后置】。。。。。");
return returnVal;
}
}
3、spring-config3.xml配置,首先导入aop和context命名空间。
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<aop:aspectj-autoproxy/>
<context:component-scan base-package="com.apesource"/>
beans>
4、测试类
public class Test04 {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config3.xml");
IUserService userService = (IUserService) context.getBean("userServiceBean");
userService.createNewUser();
userService.loginOut();
}
}