• Spring进阶之路(10)-Advice简单介绍以及通过cglib生成AOP代理对象


    Advice简单介绍


    1. Before:在目标方法运行之前运行织入。假设Before的处理中没有进行特殊的处理。那么目标方法终于会运行,可是假设想要阻止目标方法运行时。能够通过抛出一个异常来实现。Before处理无法拿到目标方法的返回值,由于这时候目标方法并未运行。

    2. AfterReturning: 返回之后运行(前提是目标方法运行成功),能够訪问到目标对象的返回值。可是不能够改变返回值。

    3. AfterThrowing:抛出异常之后运行。能够对异常进行适当的修复或者将异常输出到日志中。

    4. After:无论目标对象运行成功与否都会被织入经常使用于释放资源等。

    5. Around:既能够在目标方法之前,又能够在目标方法调用之后运行。可是须要在线程安全的情况下运行,假设须要目标方法运行之前或者之后共享某种数据。应该考虑用Around。须要改变返回值的时候,仅仅能使用Around。



    通过cglib生成AOP代理对象



    上一篇文章中已经提到,通过JDK的代理生成AOP代理对象的方式。可是前提是目标方法实现了接口,假设没有实现接口的话,那么怎么办?

    在这样的情况下,我们使用cglib来实现生成AOP代理对象。

    定义一个没有实现接口的User类。

    package com.siti.spring20160315;
    
    public class User {
    
    	private String userName;
    	private String password;
    	
    	public User(){}
    	
    	public User(String userName, String password) {
    		super();
    		this.userName = userName;
    		this.password = password;
    	}
    	
    	public String getUserName() {
    		return userName;
    	}
    	public void setUserName(String userName) {
    		this.userName = userName;
    	}
    	public String getPassword() {
    		return password;
    	}
    	public void setPassword(String password) {
    		this.password = password;
    	}
    
    	public void saySth() {
    		System.out.println("hello!");
    	}
    }


    对于Spring而言,假设说目标类实现了接口的话。会依照JDK代理生成AOP代理对象,假设没有实现接口的话,那么会使用cglib来生成AOP代理对象。


    package com.siti.spring20160315;
    
    import java.lang.reflect.Method;
    import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.InvocationHandler;
    
    
    public class MyProxy4AOPObject implements InvocationHandler{
    
    	private Object targetObj;
    	
    	public Object getProxyObject(Object targetObj){
    		this.targetObj = targetObj;
    		
    		Enhancer enhance = new Enhancer();
    		// 将目标类设置为代理对象的父类,产生目标类的子类,这个子类覆盖全部父类的非final修饰的方法
    		enhance.setSuperclass(this.targetObj.getClass());
    		// 设置回调,能够单独建立一个类实现InvocationHandler接口实现里面的invoke方法
    		enhance.setCallback(this);
    		
    		return enhance.create();
    	}
    
    	@Override
    	public Object invoke(Object proxy, Method method, Object[] args)
    			throws Throwable {
    		
    		User user = (User)this.targetObj;
    		Object result = null;
    		try{
    			// 拦截,符合要求的才同意执行
    			if(user.getUserName() != null && user.getUserName() != ""){
    				// -->Before
    				result = method.invoke(this.targetObj, args);
    				// -->AfterReturning
    			}
    		}catch (Exception e) {
    			// -->AfterThrowing
    		}finally{
    			// -->After
    		}
    		
    		return result;
    	}
    
    }
    

    package com.siti.spring20160315;
    
    public class MainTest {
    
    	public static void main(String[] args) {
    		User user = new User("wy", "wy");
    		MyProxy4AOPObject myProxy4AOPObject = new MyProxy4AOPObject();
    		User us = (User) myProxy4AOPObject.getProxyObject(user);
    		us.saySth();
    	}
    }
    这里会输出:hello!

    假设将User中name属性赋值为null或者""的话就不会输出,由于在invoke方法中进行了限制,调用的目标对象的方法不会运行。


  • 相关阅读:
    SQL横表纵表转换和对比
    计算机书籍
    附加原型链
    Object.create()
    解构赋值是浅拷贝
    Object.keys(xxx)与Object.getOwnPropertyNames(xxx)
    剑指 Offer 45. 把数组排成最小的数
    剑指 Offer 46. 把数字翻译成字符串
    剑指 Offer 43. 1~n 整数中 1 出现的次数
    剑指 Offer 41. 数据流中的中位数
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7084580.html
Copyright © 2020-2023  润新知