一.什么是代理
在实现委托类的功能的前提下,增加代理类特有的功能
二.常用代理方式
静态代理:由程序员自己创建的事实存在的代理类,在程序运行前就已经存在了,缺点也十分明显:大量的静态代理,会使得类的规模庞杂,难于维护
动态代理:程序运行时才会产生
三.静态代理分析与实例
静态代理模式必须元素
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;
}
}
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;
}
}
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();
}
}