SpringAOP的两种动态代理:JDK动态代理和cglib动态代理

AOP(Aspect-Oriented Programming,面向切面的编程),它是可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术。它是一种新的方法论,它是对传统OOP编程的一种补充。

  OOP是关注将需求功能划分为不同的并且相对独立,封装良好的类,并让它们有着属于自己的行为,依靠继承和多态等来定义彼此的关系;AOP是希望能够将通用需求功能从不相关的类当中分离出来,能够使得很多类共享一个行为,一旦发生变化,不必修改很多类,而只需要修改这个行为即可。

  AOP是使用切面(aspect)将横切关注点模块化,OOP是使用类将状态和行为模块化。在OOP的世界中,程序都是通过类和接口组织的,使用它们实现程序的核心业务逻辑是十分合适。但是对于实现横切关注点(跨越应用程序多个模块的功能需求)则十分吃力,比如日志记录,验证。

以上来自转载。我觉得简单明了。

下面就着重介绍下两种动态代理机制。

1、JDK动态代理。

JDK动态代理目标是按照接口实现类的形式。你需要创建一个jdkproxy 类来继承InvocatoinHandler 接口,将你想要动态增加的代码添加到里面的

invoke方法里,比如判断权限的代码。

首先我们创建一个目标类,也就是我们的业务代码,我们想要给他创建代理类。

目标类代码如下:

package aopdaili;

public class UserServiceImpl implements UserService{
	private User user;

	public User getUser() {
		return user;
	}

	public void setUser(User user) {
		this.user = user;
	}
	
public void saveUser() {
	System.out.println("保存用户");
}
public void updateUser() {
	System.out.println("修改用户");
}
}

里边我们有一个参数User类,和我们的业务逻辑代码,save User(),和updateUser()。

我们将在测试类里访问我们目标类里的业务代码,但是必须经过代理类里的权限判断。

代理类代码如下:jdkProxy.java

package aopdaili;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//JDK代理类是继承InvocationHandler这个接口的

public class jdkProxy implements InvocationHandler {
private Object targetObj;

public Object getTargetObj() {
	return targetObj;
}

public void setTargetObj(Object targetObj) {
	this.targetObj = targetObj;
}
  //返回语句中:第一个参数是目标类的类加载器,第二个参数是目标类的接口,
//第三个参数:设置回调对象,当前代理对象的方法被调用时,会委派该参数去调用invoke代理类负责切面:有没有权限都是在代理类里控制的。
public Object createjdkProxy(Object target) {
	this.targetObj = target;
	
	
	return Proxy.newProxyInstance(this.targetObj.getClass().getClassLoader(), 
			this.getClass().getInterfaces(), this);
	
}

public Object invoke(Object proxy, Method method, Object[] arg2) throws Throwable {
	// TODO Auto-generated method stub
	//获得目标对象的get方法
	Method getmethod = this.targetObj.getClass().getMethod("getUser", null);
	//通过反射获得调用方法的方法值
	Object user = getmethod.invoke(this.targetObj, null);
	Object obj = null;
	if(user!=null) {
		//通过调用目标对象的
		obj = method.invoke(this.targetObj, null);
		
	}else {
		System.out.println("您还没有登录!");
	}
	return obj;
}

}
@Test
	public  void test01() {
		UserServiceImpl userserviceimle = new UserServiceImpl();
		userserviceimle.setUser(null);
		//通过业务接口来接受代理对象
		UserService userservice = (UserService)new jdkProxy().createjdkProxy(userserviceimle);
		System.out.println(userservice.getClass());
		userservice.saveUser();
	}

代码具体解释都在注释标注;需要注意的就是必须继承InvocationHandler接口,将您要添加的动态代码放在Invoke方法里

测试类:

@Test
	public  void test01() {
		UserServiceImpl userserviceimle = new UserServiceImpl();
		userserviceimle.setUser(null);
		//通过业务接口来接受代理对象
		UserService userservice = (UserService)new jdkProxy().createjdkProxy(userserviceimle);
		System.out.println(userservice.getClass());
		userservice.saveUser();
	}

2、cglib动态代理

可以对普通类做动态代理,目标类不能是final类型,里面的方法也不能是final类型。

他和JDK动态代理的区别就是他是继承MethodInterceptor接口。将你想增加的代码添加到intercept方法里。

他的代理类代码如下:

package aopdaili;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

public class cglibProxy implements MethodInterceptor {
	
	private  Object targetObj;
	
	public Object createProxyInstance( Object targetObj) {
		this.targetObj = targetObj;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.targetObj.getClass());
		enhancer.setCallback(this);
		return enhancer.create();
		
	}
	

	public Object intercept(Object arg0, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
		// TODO Auto-generated method stub
		//获得目标对象的get方法
		Method getmethod = this.targetObj.getClass().getMethod("getUser", null);
		//通过反射获得调用方法的方法值
		Object user = getmethod.invoke(this.targetObj, null);
		Object obj = null;
		if(user!=null) {
			//通过调用目标对象的
			obj = method.invoke(this.targetObj, arg2);
			
		}else {
			System.out.println("您还没有登录!");
		}
		return obj;
	}

}

其他代码一样。
















展开阅读全文

没有更多推荐了,返回首页