spring-AOP动态代理,以及aspectJ的xml配置或注解配置方法,各个拦截器的使用顺序

package com.itheima.aspect;

public class MyAspect {
	public void check_Permissions(){
		System.out.println("模拟检查权限...");
	}
	public void log() {
		// TODO Auto-generated method stub
		System.out.println("记录日志");
	}
}

  

package com.itheima.aspect;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


import com.itheima.jdk.UserDao;

public class JdkProxy implements InvocationHandler{
	private UserDao userDao;
	public Object createProxy(UserDao userDao){
		this.userDao=userDao;
		ClassLoader classLoader=JdkProxy.class.getClassLoader();
		Class[]clazz = userDao.getClass().getInterfaces();
		return Proxy.newProxyInstance(classLoader, clazz, this);
		
	}
	@Override
	public Object invoke(Object proxy,Method method,Object[]args)
	throws Throwable{
		MyAspect myAspect = new MyAspect();
		myAspect.check_Permissions();
		Object obj = method.invoke(userDao,args);
		myAspect.log();
		return obj;
	}
}

  

package com.itheima.aspect;

import com.itheima.jdk.UserDao;
import com.itheima.jdk.UserDaoImpl;

public class JdkTest {
	public static void main(String[] args) {
		JdkProxy jdkProxy= new JdkProxy();
		UserDao  userDao = new UserDaoImpl();
		UserDao userDao1= (UserDao)jdkProxy.createProxy(userDao);
		userDao1.addUser();
		userDao1.deleteUser();
	}
}

  

 AOP动态代理方法的实现如上,不过总体来说还是比较麻烦,要修改的地方也太多。

后来有人开发了aspectJ工具,通过aspectJ,可以方便的使用切面,把代理类和实现类与代理类之间的耦合解除。

aspectJ有两种实现方式,一种是xml,一种是注解。

这里要注意需要导入aspectJ的相关包

方式1:通过xml实现

  将代理类和实现类与代理类之间的调用关系,全部写进xml中:

即以上的代码修改一下:

切面:

  

package com.itheima.aspectj.xml;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;

public class MyAspect {
	public void myBefore(JoinPoint joinPoint){
		System.out.println("前置通知");
		System.out.println("目标类是:"+joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	public void myAfterReturning(JoinPoint joinPoint){
		System.out.println("后置通知");
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	public Object myAround(ProceedingJoinPoint joinPoint)
		throws Throwable{
		System.out.println("环绕开始:执行方法之前,模拟开启事务");
		Object object=joinPoint.proceed();
		System.out.println("环绕结束:执行方法之后,模拟关闭事务");
		return object;
	}
	public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
		System.out.println("异常通知:"+"出错了"+e.getMessage());
		System.out.println("目标类是:"+joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	public void myAfter(JoinPoint joinPoint){
		System.out.println("最终通知:模拟方法结束后释放资源");
	}
}

  

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:context="http://www.springframework.org/schema/context"
 xmlns:mvc="http://www.springframework.org/schema/mvc"
 xmlns:aop="http://www.springframework.org/schema/aop"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc 
 http://www.springframework.org/schema/mvc/spring-mvc-3.1.1.xsd
 http://www.springframework.org/schema/beans 
 http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
 http://www.springframework.org/schema/context 
 http://www.springframework.org/schema/context/spring-context-4.3.xsd
 http://www.springframework.org/schema/aop
 http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
	<bean id = "userDao" class = "com.itheima.jdk.UserDaoImpl"/>
	<bean id = "myAspect" class = "com.itheima.aspectj.xml.MyAspect"/>
<aop:config>
		<aop:aspect id = "aspect" ref = "myAspect">
			<aop:pointcut expression = "execution(* com.itheima.jdk.*.*(..))" 
			id = "myPointCut"/>
			<aop:before method = "myBefore" pointcut-ref="myPointCut"/>
			<aop:after-returning method="myAfterReturning" 
				pointcut-ref = "myPointCut" returning = "returnVal"/>
			<aop:around method="myAround" pointcut-ref="myPointCut"/>
			<aop:after-throwing method = "myAfterThrowing"
				pointcut-ref = "myPointCut" throwing="e"/>
			<aop:after method="myAfter" pointcut-ref="myPointCut"/>
		</aop:aspect>
</aop:config>
</beans>
	

 

测试类:

package com.itheima.aspectj.xml;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.itheima.jdk.UserDao;
public class AspectjXmlTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = 
				new ClassPathXmlApplicationContext("com/itheima/aspectj/xml/applicationContext.xml");
		UserDao userDao= (UserDao) applicationContext.getBean("userDao");
		userDao.addUser();
		userDao.deleteUser();
	}
}

  

执行结果:

前置通知
目标类是:com.itheima.jdk.UserDaoImpl@59309333
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.addUser()
环绕开始:执行方法之前,模拟开启事务
添加用户
最终通知:模拟方法结束后释放资源
环绕结束:执行方法之后,模拟关闭事务
后置通知
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.addUser()
前置通知
目标类是:com.itheima.jdk.UserDaoImpl@59309333
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.deleteUser()
环绕开始:执行方法之前,模拟开启事务
删除用户
最终通知:模拟方法结束后释放资源
环绕结束:执行方法之后,模拟关闭事务
后置通知
,被植入增强处理的目标方法位:void com.itheima.jdk.UserDao.deleteUser()

  

 aspectJ减少了动态代理实现中出现的代码臃肿,但是,需要修改spring的配置文件,不是很好。

于是衍生了注解方式实现AOP,完美解决了修改spring配置文件的问题。

package com.itheima.aspectj.annotation;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class MyAspect {
	//defined the pointcut
	@Pointcut("execution(* com.itheima.jdk.*.*(..))")
	private void myPointCut(){}
	//pre-notification
	@Before("myPointCut()")
	public void myBefore(JoinPoint joinPoint){
		System.out.println("前置通知");
		System.out.println("目标类是:"+joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	//after-notification
	@AfterReturning(value="myPointCut()")
	public void myAfterReturning(JoinPoint joinPoint){
		System.out.println("后置通知");
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	//around-notification
	@Around("myPointCut()")
	public Object myAround(ProceedingJoinPoint joinPoint)
		throws Throwable{
		System.out.println("环绕开始:执行方法之前,模拟开启事务");
		Object object=joinPoint.proceed();
		System.out.println("环绕结束:执行方法之后,模拟关闭事务");
		return object;
	}
	@AfterThrowing(value="myPointCut()",throwing="e")
	public void myAfterThrowing(JoinPoint joinPoint,Throwable e){
		System.out.println("异常通知:"+"出错了"+e.getMessage());
		System.out.println("目标类是:"+joinPoint.getTarget());
		System.out.println(",被植入增强处理的目标方法位:"+joinPoint.getSignature());
	}
	@After("myPointCut()")
	public void myAfter(JoinPoint joinPoint){
		System.out.println("最终通知:模拟方法结束后释放资源");
	}
}

  

	<context:component-scan base-package="com.itheima" />
	<aop:aspectj-autoproxy />
	

  

public class AspectjXmlTest {
	public static void main(String[] args) {
		ClassPathXmlApplicationContext applicationContext = 
				new ClassPathXmlApplicationContext("com/itheima/aspectj/annotation/applicationContext.xml");
		UserDao userDao= (UserDao) applicationContext.getBean("userDao");
		userDao.addUser();
		userDao.deleteUser();
	}
}

  

posted @ 2019-05-05 15:14  头鹰在学习  阅读(735)  评论(0编辑  收藏  举报