java代理模式(静态代理,jdk代理,cglib代理)

一、静态代理
要求:被代理类必须实现至少一个接口;代理类(程序员自己编写)也必须实现被代理类的接口,且实现其中的方法;代理类必须代理被代理类。
示例:
1、被代理类实现的接口:

public interface MoneyService {
	public void sava(int money);
	public void send(String src,String dest,int money);
}

2、被代理类:

public class MoneyServiceImpl implements MoneyService{

	@Override
	public void sava(int money) {
		System.out.println("调用dao执行sql,存钱");
	}

	@Override
	public void send(String src, String dest, int money) {
		System.out.println("在转出人账户上减1000块钱");
		System.out.println("在目标账户上加1000块钱");
	}
}

代理类:

public class MoneyServiceProxy implements MoneyService{
	private MoneyService target;//目标、代理、委托
	public MoneyServiceProxy(MoneyService target) {
		super();
		this.target=target;
	}
	@Override
	public void sava(int money) {
		System.out.println("开启事务");
		target.sava(money);
		System.out.println("提交事务");
	}

	@Override
	public void send(String src, String dest, int money) {
		System.out.println("开启事务");
		target.send(src, dest, money);
		System.out.println("提交事务");
	}

}

测试类:

public class StaticDelegate {
	public static void main(String[] args) {
		//创建代理类对象并且指定一个被代理类对象
		MoneyService moneyService = new MoneyServiceProxy(new MoneyServiceImpl());
		//调用service方法
		moneyService.sava(1000);
		moneyService.send("", "", 1000);
	}
}

二、动态代理
1、JDK代理:使用Proxy类,可以自动生成代理类及代理类对象
要求:被代理类必须实现至少一个接口。
被代理类接口:

public interface MoneyService {
	public void sava(int money);
	public void send(String src,String dest,int money);
}

被代理类:

public class MoneyServiceImpl implements MoneyService{

	@Override
	public void sava(int money) {
		System.out.println("调用dao执行sql,存钱");
	}

	@Override
	public void send(String src, String dest, int money) {
		System.out.println("在转出人账户上减1000块钱");
		System.out.println("在目标账户上加1000块钱");
	}
}

代理类工厂:

/*
 * 代理类工厂:自动生成代理类以及代理类对象
 * 1、拥有一个被代理类的对象
 * 2、提供一个方法来获取代理类对象
 */
public  class ProxyFactory {
	private Object target;//被代理类对象
	public ProxyFactory(Object target) {
		super();
		this.target=target;
	}
	//获取代代理类对象
	public Object getProxyInstance() {
		/*
		 * Proxy.newProxyInstance()
		 * 参数一:类加载器
		 * 参数二:被代理类实现的所有接口
		 * 参数三:方法处理器/方法拦截器
		 * 
		 * 这个方法会自动生成一个类,而且该类驶向了target.getClass().getInterfaces()接口
		 */
		return Proxy.newProxyInstance(ProxyFactory.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {//用于拦截代理类的方法,拦截后执行下面的invoke方法
			/*
			 * invoke()
			 * 参数一:代理类对象
			 * 参数二:被调用的方法
			 * 参数三:调用方法时传入的参数
			 */
			@Override
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				System.out.println("开启事务");
				//被代理类对象调用方法(执行SQL)
				Object result = method.invoke(target, args);//执行被代理类方法
				System.out.println("提交事务");
				return result;
			}
		});
	}
}

测试类:

public class Base {
	public static void main(String[] args) {
		ProxyFactory factory = new ProxyFactory(new MoneyServiceImpl());
		Object obj = factory.getProxyInstance();
		//
		System.out.println(obj.getClass());
		
		System.out.println(obj instanceof MoneyService);
		if(obj instanceof MoneyService) {
			MoneyService moneyService = (MoneyService) obj;
			//调方法
			moneyService.sava(1000);//调用代理类对象的方法,该方法将被代理类工厂中的方法处理器(方法拦截器)处理(拦截),之后将会执行处理器中的invoke方法,实现代理。
		}
	}
}

2、CGLIB代理:又称为子类代理,就是为被代理类自动生成一个子类
要求:需要第三方jar包;代理类需要实现jar包中的MethodInterceptor接口。
需要的第三方包:asm-3.3.1.jar;cglib-2.2.2.jar
被代理类:

public class UserService {
	public void add() {
		System.out.println("调用sql语句添加用户");
	}
}

代理类工厂:

/*
 * cglib动态代理工厂:创建代理类对象
 * 1、实现方法拦截器接口(MethodInterceptor)
 * 2、拥有一个被代理类对象
 */
public class CglibProxyFactory implements MethodInterceptor{
	private Object target;
	public CglibProxyFactory(Object target) {
		super();
		this.target=target;
	}
	/*
	 *obj    代表Cglib 生成的动态代理类 对象本身
	 *method 代理类中被拦截的接口方法 Method 实例
	 *args   接口方法参数
	 *proxy  用于调用父类真正的业务类方法。可以直接调用被代理类接口方法
	 */
	@Override
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		System.out.println("cglib开启事务");
		Object result = method.invoke(target, args);
		System.out.println("cglib提交事务");
		return result;
	}
	//返回代理类对象
	public Object getProxyInstance() {
		//1、创建生成代理类的工具类
		Enhancer enhancer = new Enhancer();
		//2、指定代理类的父类是哪个类
		enhancer.setSuperclass(target.getClass());
		//3、设置回调函数
		enhancer.setCallback(this);
		//4、生成代理类对象
		return enhancer.create();
	}
}

测试类:

public class TestCglib {

	public static void main(String[] args) {
		CglibProxyFactory factory = new CglibProxyFactory(new UserService());
		//获取代理类对象
		Object obj = factory.getProxyInstance();
		System.out.println(obj.getClass());
		
		if(obj instanceof UserService) {
			System.out.println("yes");
			UserService userService = (UserService) obj;
			userService.add();
		}
	}

}

静态代理:由程序员编辑代理类代码,实现代理模式;在编译期就生成了代理类。

基于 JDK 实现动态代理:
通过jdk提供的工具方法Proxy.newProxyInstance动态构建全新的代理类(继承Proxy类,并持有InvocationHandler接口引用 )字节码文件并实例化对象返回。(jdk动态代理是由java内部的反射机制来实例化代理对象,并代理的调用委托类方法)
被代理类和代理类的关系:兄弟、同胞关系
缺点:被代理类至少需要实现一个接口。

基于CGlib 动态代理模式:
基于继承被代理类生成代理子类,不用实现接口。只需要被代理类是非final 类即可。(cglib动态代理底层是借助asm字节码技术
代理类和被代理类的关系:继承关系(代理类继承被代理类)

©️2020 CSDN 皮肤主题: 1024 设计师:上身试试 返回首页