动态代理是为了解决静态代理每次添加新功能都需要新创建代理类的问题。动态代理分为两种,一张是jdk动态代理,一种是cglib动态代理,两种实现动态代理的方法不一样,但是结果是一样的。
1.JDK动态代理
JDK动态代理创建一个代理类需要实现InvocationHandler接口,接口中有invoke方法,方法有三个参数
参数1代表被代理的目标对象
参数2表示被代理目标对象中的方法
参数3代表参数
package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class TicketHandler implements InvocationHandler {
private Object office;
public TicketHandler(Object office)
{
this.office=office;
}
//proxy被代理的对象
//method被代理对象的方法
//args方法参数
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
System.out.println("提供茶水,提供无线网络");
method.invoke(office);
System.out.println("提供午餐");
return null;
}
}
public static void main( String[] args )
{
TicketOffice office=new TicketOffice();
//创建代理对象
/* Ticket proxy=new ProxyTicket(office);
proxy.SaleTicket();*/
Class<?> c=office.getClass();
InvocationHandler handler=new TicketHandler(office);
//参数1是类加载器
//参数2是实现的接口
//创建代理对象
Ticket t=(Ticket)Proxy.newProxyInstance(c.getClassLoader(), c.getInterfaces(), handler);
t.SaleTicket();
}
实现代理需要使用Proxy.newProxyInstance方法创建代理对象。方法同样有三个参数,参数1表示类目标对象加载器,参数2表示目标对象实现的接口。参数3表示添加新功能的handler. 这样同们就可以创建代理对象,并调用目标对象中的方法。但是使用JDK有一个问题,如果目录对象没有继承接口怎么办,我们就没办法使用JDK代理了。JAVA为我们提供了另一种代理方式cglib代理
2.CGLIB动态代理
cglib动态代理需要实现MethodInterceptor接口,接口中有intercept拦截方法,有四个参数
参数1表示目标对象的实例
参数2表示目标对象的方法
参数3表示方法参数
//参数4表示代理对象
使用cglib代理目标对象不需要继承接口
package com.proxy;
public class Ticket {
public void SaleTicket() {
// TODO Auto-generated method stub
System.out.println("售卖火车票");
}
}
package com.proxy;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class cgLibProxy implements MethodInterceptor {
Enhancer hancer=new Enhancer();
public Object CreateProxy(Class cls)
{
hancer.setSuperclass(cls);//设置创建类的子类
hancer.setCallback(this);
return hancer.create();//返回代理对象
}
//参数1表示目标对象的实例
//参数2表示目标对象的方法
//参数3表示方法参数
//参数4表示代理对象
public Object intercept(Object arg0, Method arg1, Object[] arg2,
MethodProxy arg3) throws Throwable {
// TODO Auto-generated method stub
System.out.println("提供茶水,提供WIFI");
arg3.invokeSuper(arg0, arg2);
return null;
}
}
public static void main( String[] args )
{
cgLibProxy proxy=new cgLibProxy();
Ticket t=(Ticket)proxy.CreateProxy(Ticket.class);
t.SaleTicket();
}
使用CGLIB代理需要引入CGLIB包
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.4</version>
</dependency>