使用JDK动态代理和CGLib代理生成代理对象来增强方法

*以下操作的前提是引入spring相关jar包

*在实际spring开发中,不需要手写代码来生成代理对象。可以通过配置文件的方式来完成。

一、使用JDK动态代理

注意事项:JDK动态代理使用的前提是:代理的对象必须至少实现了一个接口。

1、接口和实现类(代理对象)

public interface UserDao {
	public void add();
	public void update();
	
}
package cn.itcast.demo1;

public class UserDaoImp implements UserDao {

	@Override
	public void add() {
		System.out.println("this is add....");

	}

	@Override
	public void update() {
		System.out.println("this is update....");
	}

}

2、动态代理(重点)

package cn.itcast.demo1;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
 * 使用jdk动态代理,增强方法
 * 想使用jdk动态代理,代理对象类必须实现至少一个接口 
 * @author Mr.Tong
 *
 */
//继承InvocationHandler
public class JDKProxy implements InvocationHandler{
	private UserDao userDao;//想使用jdk动态代理,代理对象类必须实现至少一个接口

	public JDKProxy(UserDao userDao) {
		super();
		this.userDao = userDao;
	}
	public UserDao createProxy(){
		//利用接口获得一个增强后的代理对象
		UserDao proxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), userDao.getClass().getInterfaces(), this);
		return proxy;
	}
	//调用对象的任何一个方法,都会执行该方法
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		 if("add".equals(method.getName())){
			 System.out.println("这里是add方法的增强部分");
			 Object result = method.invoke(userDao, args);
		 }
		 if("update".equals(method.getName())){
			 System.out.println("这里是update方法的增强部分");
			 Object result = method.invoke(userDao, args);
		 }
		return null;
	}
	
}

3、测试

package cn.itcast.demo1;

import org.junit.Test;

public class Test1 {
	@Test
	//不使用动态代理
	public void demo1(){
		 UserDao dao = new UserDaoImp();
		 dao.add();
		 dao.update();
	}
	@Test
	public void demo2(){
		UserDao userDao = new UserDaoImp();//实例化一个需要增强的对象
		UserDao daoProxy = new JDKProxy(userDao).createProxy();//jdk动态代理 返回一个增强之后的对象
		daoProxy.add();
	}
}

二、使用CGLib代理

1、代理对象

package cn.itcast.demo2;

public class ProductDao {
	public void add(){
		System.out.println("this is add....");
	}
	public void update(){
		System.out.println("this is update....");
	}
}

2、生成代理(重点)

package cn.itcast.demo2;

import java.lang.reflect.Method;
 
import org.springframework.cglib.proxy.Callback;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodProxy;
/**
 * CGLib生成代理的机制是继承
 * @author Mr.Tong
 *
 */
//继承cglib的MethodInterceptor
public class CGLibProxy implements org.springframework.cglib.proxy.MethodInterceptor{
	private ProductDao productDao;

	public CGLibProxy(ProductDao productDao) {
		super();
		this.productDao = productDao;
	}
	public ProductDao creatCGLibProxy(){
		//使用CGLib生成代理
		//1、创建核心类
		Enhancer enhancer = new Enhancer();
		//2、为它设置父类
		enhancer.setSuperclass(productDao.getClass());
		//3、设置回调
		enhancer.setCallback((Callback) this);
		return (ProductDao) enhancer.create();
	}
	@Override
	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		if ("add".equals(method.getName())) {
			System.out.println("CGLib代理对象add方法的增强部分");
			Object result = methodProxy.invokeSuper(proxy, args);
			return result;
		}
		return methodProxy.invokeSuper(proxy, args);
	}
	
	 
}

3、测试

package cn.itcast.demo2;

import org.junit.Test;

public class Test2 {
	@Test
	public void demo1(){
		 ProductDao productDao = new ProductDao();
		ProductDao productDao2 = new CGLibProxy(productDao).creatCGLibProxy();
		productDao2.add();
	}
}

*结论:如果类实现了接口,就用jdk动态代理。没有实现接口就用cglib代理。

猜你喜欢

转载自blog.csdn.net/xiaoshuo566/article/details/83792761