手写简单的SpringAOP动态代理的方式

SpringAOP代理模式

一、JDK动态代理模式

1、JDK动态代理的原理

  • 通过实现InvocationHandler接口创建自己的调用处理器
  • 通过为Proxy类指定ClassLoader对象和一组Interface来创建
  • 通过反射机制获取动态代理的构造函数
  • 通过构造函数创建动态代理的实例

2、JDK动态代理demo

UserDao 接口

	package demo;
	public interface UserDao {
	public void save();
	public void update();
	public void delete();
	public void select();
}

UserDaoImpl接口实现

package demo;
public class UserDaoImpl implements UserDao {
public void save() {
	System.out.println("保存");
}
public void update() {
	System.out.println("更新");
}
public void delete() {
	System.out.println("删除");
}
public void select() {
	System.out.println("查询");
}
}

JDK动态代理

package demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler{
//将被增加的对象传递到代理中
private UserDao userDao;
public JdkProxy(UserDao userDao) {
	this.userDao=userDao;
}
/**
 * 产生UserDao代理的方法
 * @return
 */
public UserDao createProxy() {
	//第一个参数:增加类的类加载器
	//第二个参数:类的接口
	//第三个参数:InvocationHandler 动态代理类直接实现handler的接口,第三个参数可以调用自身
	UserDao userDaoProxy=(UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), 
			userDao.getClass().getInterfaces(), this);
	return userDaoProxy;	
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
	// 判断方法名是不是save
	if("save".equals(method.getName())) {
		//增强
		System.out.println("增加权限成功");
		return method.invoke(userDao, args);
	}
	return method.invoke(userDao, args);
}
}

这里就简单的增强了 save() 这个方法

二、Cglib动态代理

1、Cglib动态代理原理

CGLib采用了非常底层的字节码技术,其原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。

2、代理Demo

CustomerDao

package demo2;

public class CustomerDao {
public void save() {
	System.out.println("cglib  保存");
}

public void update() {
	System.out.println("cglib  更新");
}

public void delete() {
	System.out.println("cglib  删除");
}

public void select() {
	System.out.println("cglib  查询");
}
}

CglibProxy

package demo2;

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 CustomerDao customerDao;
public CglibProxy(CustomerDao customerDao) {
	this.customerDao=customerDao;
}
public CustomerDao createProxy() {
	//1.创建cglib的核心对象
	Enhancer enhancer=new Enhancer();
	//2.设置父类
	enhancer.setSuperclass(customerDao.getClass());
	//3.设置回调:(类似于InvocationHandler对象)
	enhancer.setCallback(this);
	//4.创建代理对象
	CustomerDao create = (CustomerDao) enhancer.create();
	return create;
}
public Object intercept(Object proxy, Method medthod, Object[] arg2, MethodProxy methodProxy) throws Throwable {
	// 判断方法是否为save
	if("save".equals(medthod.getName())) {
		System.out.println("cglib 增强");
		return methodProxy.invokeSuper(proxy, arg2); 
	}
	return methodProxy.invokeSuper(proxy, arg2); //如果不是save方法,那就直接执行父类的方法,不增强
}
}

三、两者的区别

1、代理的区别

  • JDK动态代理是面向接口的
  • Cglib动态代理是通过字节码底层继承要代理类来实现的
    而spring是模式采用JDK动态代理的实现机制,如果代理的不是实现类,那么会采用Cglib来实现动态代理

2、性能的区别

  • Cglib动态代理所创建的代理在运行时的性能会比JDK动态代理高出不少
  • 而在创建对象时Cglib所用的时间会比JDK动态代理要多很多
    所以,无需频繁的创建对象时使用Cglib动态代理要好很多,如一些单例的代理,反之则使用JDK动态代理
全部评论

相关推荐

点赞 1 评论
分享
牛客网
牛客企业服务