Java动态代理JDK与Cglib

一.什么是代理

在实现委托类的功能的前提下,增加代理类特有的功能

二.常用代理方式

静态代理:由程序员自己创建的事实存在的代理类,在程序运行前就已经存在了,缺点也十分明显:大量的静态代理,会使得类的规模庞杂,难于维护

动态代理:程序运行时才会产生

三.静态代理分析与实例

静态代理模式必须元素

1.Service接口——用于定义业务

2.ServiceImp类——实现具体业务

3.Proxy类——代理类,调用ServiceImp实现具体业务,并且调用自己的业务

具体案例,通过静态代理实现车票代售服务

1.Service接口

public interface TicketService {
	//车票查询
	public void queryTicket();
	//车票售卖
	public void sellTicket();
}

2.ServiceImp类

public class Station implements TicketService{
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

3.Proxy类

public class ProxyStation implements TicketService{
	private Station ts;

	public ProxyStation(Station ts) {
		this.ts = ts;
	}

	@Override
	public void queryTicket() {
		System.out.println("proxy to do");
		ts.queryTicket();
	}

	@Override
	public void sellTicket() {
		System.out.println("proxy to do");
		ts.sellTicket();
	}

四.动态代理分析与实例

动态代理类的字节码在程序运行时通过java反射机制动态生成,无需程序员手动编写,这样就简化了编程工作,提高了软件系统扩展与维护性能

在这里简单介绍常用的两种动态代理方式——JDK与Cglib

        1.JDK(通过接口实现代理)

具体实现流程

1.获取ServiceImp上的所有接口

2.动态创建Proxy类的字节码并且转换为class

3.创建InvocationHandler的实例以处理Proxy所有方法调用

4.Proxy以创建的InvocationHandler对象为参数实例化一个Proxy

        在这里引入了一个新的类InvocationHandler

      InvocationHandler的存在意义:不同于静态代理,对于每个接口方法都重写,然后去调用具体实现类中的方法,而是将所有的方法都交给了InvocationHandler管理,让其调用具体实现类的对应业务方法,所以JDK实现动态代理的缺点也很明显,只能代理接口定义的方法

       案例实现

1.Service接口

public interface TicketService {
	//车票查询
	public void queryTicket();
	//车票售卖
	public void sellTicket();
}

2.ServiceImp类

public class Station implements TicketService{
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

3.Proxy类

public class TicketStationProxy implements InvocationHandler{
	private TicketStation ticketStation;
	

	public TicketStationProxy(TicketStation ticketStation) {
		this.ticketStation = ticketStation;
	}


	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("going to "+method.getName());
		method.invoke(ticketStation, args);
		return null;
	}

}


4.Test测试

public class Test {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TicketStation ts = new TicketStation();
		TicketStationProxy proxy = new TicketStationProxy(ts);
		ClassLoader classLoader = ts.getClass().getClassLoader();
		Class<?>[] interFace = ts.getClass().getInterfaces();
		TicketService tsProxy = (TicketService) Proxy.newProxyInstance(classLoader, interFace, proxy);
		tsProxy.queryTicket();
	}

}


2.Cglib实现动态代理流程与分析

1.查找委托类上所有非final的public方法

2.将获取方法转换成对应的字节码,组合并且生成对应的class

3.通过实现MethodInterceptor接口来处理proxy上对应的所有业务方法

MethodInterceptor作用类似InvocationHandler


案例分析

1.Service委托类

public class Station {
	public void queryTicket() {
		System.out.println("query ticket..");
	}
	public void sellTicket() {
		System.out.println("sell ticket..");
	}

}

2.代理类

代理类中包含一个返回代理对象的方法,具体实现方法

1.创建一个Enhancer对象,设置Enhancer

public class TicketCg implements MethodInterceptor { 
	private TicketStation ts;
	public Object getInstance(TicketStation ts) {
		this.ts = ts;
		Enhancer en = new Enhancer();
		en.setSuperclass(this.ts.getClass());
		en.setCallback(this);
		return en.create();
	}

	@Override
	public Object intercept(Object obj, Method arg1, Object[] arg2,
			MethodProxy arg3) throws Throwable {
		System.out.println("Cglib going to "+arg1.getName());
		// TODO Auto-generated method stub
		arg1.invoke(ts, arg2);
		return obj;
	}

}


3.Test

public class CglibTest {
	public static void main(String[] args) throws InterruptedException{
		TicketStation ts = new TicketStation();
		TicketCg tc = new TicketCg();
		TicketStation proxy = (TicketStation) tc.getInstance(ts);
		proxy.queryTicke();
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值