代理模式
静态代理
代理的实现完全由程序员自己来实现 改实现只能针对特定的对象来实现代理(就是对被代理对象起到一个增强的作用。)
实现步骤
- 定义主业务的接口
- 实现接口
- 通过代理来增强主业务方法
package org.lanqiao.proxy.demo;
//被代理对象
public class Customer implements SallTicket {
@Override
public void buyTicket() {
System.out.println("购买一张太原到北京的动车票");
}
}
package org.lanqiao.proxy.demo;
//代理对象
public class TicketApp implements SallTicket {
// 需要被代理对象
private Customer cus ;
//绑定代理对象
public TicketApp(Customer cus) {
this.cus = cus;
}
@Override
public void buyTicket() {
System.out.println("检查用户是否登陆成功");
cus.buyTicket();
System.out.println("收取火车票钱");
}
}
package org.lanqiao.proxy.demo;
public interface SallTicket {
public void buyTicket();
}
package org.lanqiao.proxy.demo;
public class Test {
public static void main(String[] args) {
Customer cus = new Customer();
TicketApp ta = new TicketApp(cus);
ta.buyTicket();
}
}
动态代理:
1、jdk提供的代理的实现:
代理对象必须实现接口(代理的是接口)
步骤
- 定义主业务逻辑接口
- 实现该接口
- 编写针对代理对象的处理方式 implements InvocationHandler
只有这一个方法,还可查询Proxy类
Proxy
提供用于创建动态代理类和实例的静态方法,它还是由这些方法创建的所有动态代理类的超类。
使用的步骤
- 创建被代理对象的实例
- 创建代理的处理器对象并绑定被代理对象
- 创建代理对象 (被代理对象的接口)
- 通过代理对象调用主业务逻辑方法。
package org.lanqiao.jdkproxy.demo;
/*
* 主业务逻辑接口
*/
public interface BuyTicket {
public void buy();
}
package org.lanqiao.jdkproxy.demo;
/*
* 被代理对象
*/
public class Customer implements BuyTicket {
@Override
public void buy() {
System.out.println("购买一张从太原到北京的火车票");
}
}
package org.lanqiao.jdkproxy.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/*
* 代理对象
*/
public class MyInvocationHandler implements InvocationHandler {
private Object target;//代理的目标对象
//初始化目标对象
public MyInvocationHandler(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("检查用户是否登陆成功");
method.invoke(target, args);
System.out.println("付款");
return null;
}
}
package org.lanqiao.jdkproxy.demo;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
Customer cus = new Customer();//创建代理对象
MyInvocationHandler Myih = new MyInvocationHandler(cus);//代理的处理方法
//通过Proxy产生代理接口的对象
BuyTicket buyProxy = (BuyTicket) Proxy.newProxyInstance(cus.getClass().getClassLoader(), cus.getClass().getInterfaces(), Myih);
buyProxy.buy();//通过代理对象调用业务方法
}
}
2、第三方的代理框架:cglib
Cglib是一个优秀的动态代理框架,它的底层使用ASM在内存中动态的生成被代理类的子类,使用CGLIB即使代理类煤与实现任何接口也可以实现动态代理功能。CGLIB具有简单易用,它的运行速度要远远快于JDK的Proxy动态代理。
注意:我们所使用的 cglib 不是jdk提供的,是由别人提供的,所以不能直接使用。在使用别人提供的cglib时,别人会将需要的类打包成jar包,如图所示这两个文件,cglib是核心类jar包,asm是依赖类的jar包
把他们复制一下,在项目下新建一个文件夹 lib ,复制到里面去,然后选中这两个jar包右键,找到build path-->Add build path,这样就把jar包加入到我们当前的工程中。(这些步骤是在 eclipse 下完成的)
步骤
1、实现主业务逻辑
2、实现 MethodInterceptor方法代理接口,创建代理类
① 需要增强器:Enhancer
// 设置代理类的父类 增强器所要增强的目标类
en.setSuperclass(clazz);
//设置回调方法 当增强完成之后 所需要执行的方法
en.setCallback(this);
//返回代理对象
return en.create();//增强之后的对象
② 实现interceptor方法
在执行代理方法之前所需要执行的方法或代码
使用methodProxy.supperInvoke(被代理对象,方法参数);
在执行代理方法之后所需要执行的方法或代码
3、使用
① 生成代理对象
② 通过代理对象获取增强之后的对象 被代理对象
③ 增强后的对象执行目标方法
package org.lanqiao.cglib.demo;
/*
* 被代理对象 主业务逻辑
* 使用cglib做代理 不需要实现接口
*/
public class Customer {
public void buyTicket( int money) {
System.out.println("购买一张从太原到北京的动车票");
}
}
package org.lanqiao.cglib.demo;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/*
* 代理类 :MethodInterceptor
*/
public class TicketAppCglib implements MethodInterceptor{
// 需要创建增强器
private Enhancer en = new Enhancer();
//获取代理对象
public Object getProxyObj(Class<?> clazz) {
// 设置代理类的父类 增强器所要增强的目标类
en.setSuperclass(clazz);
//设置回调方法 当增强完成之后 所需要执行的方法
en.setCallback(this);
//返回代理对象
return en.create();//增强之后的对象
}
//拦截器 对要执行的方法进行拦截
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
System.out.println("检查用户是否登陆");
methodProxy.invokeSuper(obj, args);
System.out.println(args[0]);
System.out.println("付款");
return null;
}
}
package org.lanqiao.cglib.demo;
public class Test {
public static void main(String[] args) {
//Customer cus = new Customer();
TicketAppCglib cglib = new TicketAppCglib();
Customer cusProxy = (Customer) cglib.getProxyObj(Customer.class);
cusProxy.buyTicket(200);
}
}