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方法中进行了限制,调用的目标对象的方法不会执行。


你可能感兴趣的:(spring)