• 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();
    	}
    }
    

      

  • 相关阅读:
    sqlserver中递归写法
    keytools命令生成证书
    java中sql语句快速处理
    select * 替换写法
    oracle行转列
    oracle中查看当前用户的表结构、主键、索引
    Servlet三种实现方式
    【python之旅】python的面向对象
    【python之旅】python的模块
    【python之旅】python的基础三
  • 原文地址:https://www.cnblogs.com/zhizhiyin/p/10813198.html
Copyright © 2020-2023  润新知