背景
代理模式的主要作用是为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。
在实际应用中对用于对调用的方法进行拦截然后将方法增强以适应各种特殊的需求场景!!
代理分为静态代理和动态代理,区分就是静态代理是编译时就生成的,而动态代理是运行时生成的!!这里主要是看需要,没有绝对的好坏,静态代理速度快,而动态代理灵活!!
静态代理
简单的说就是让代理类也去实现被代理类的接口!!换句话说被代理的对象和代理类都实现了同一个接口,然后对这个接口定义的方法进行增强。
下面是通用框架:
//被代理的公共接口
interface Subject {
// 定义了一个方法
public void request();
}
//被代理对象
class RealSubject implements Subject {
// 实现方法
public void request() {
// 业务处理
}
}
//代理类
class Proxy implements Subject {
// 要代理哪个实现类
private Subject subject = null;
public Proxy(Subject subject) {
this.subject = subject
}
// 实现接口中定义的方法
public void request() {
this.before();
this.subject.request();
this.after();
}
// 增强处理
private void before() {
// do something
}
// 增强处理
private void after() {
// do something
}
}
实现
定义一个"吃"的接口,现在对这个接口代理一下,增强”吃“方法,比如洗手洗碗。。。。下面是代理结构:
public interface IEat {
void eat();
}
public class EatImpl implements IEat {
@Override
public void eat() {
System.out.println("我要吃!!");
}
}
public class Proxy implements IEat {
private IEat proxyObject;
public Proxy(IEat proxyObject){
this.proxyObject=proxyObject;
}
@Override
public void eat() {
eatbefore();
proxyObject.eat();
eatafter();
}
//增强方法
private void eatafter() {
System.out.println("去洗碗筷!!");
}
private void eatbefore() {
System.out.println("先洗手!!");
}
}
最后调用实现类:
public class StaticProxyTest {
public static void main(String[] args) {
IEat proxyedObject=new EatImpl();
Proxy proxy = new Proxy(proxyedObject);
proxy.eat();
}
}
动态代理
Java动态代理机制中有两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是我们实现动态代理的核心,利用反射机制生成一个实现代理接口的匿名类。
这里自己的注意的是:JDK动态代理只能代理实现了接口的类,没有实现接口的类是不能实现JDK动态代理。
实现
还是上面的吃的例子,下面是代理结构:
IEat和EatImpl是没有变,下面就是jdk代理的核心:
public class JdkProxy implements InvocationHandler {
private Object obj;
public JdkProxy(Object obj){
this.obj=obj;
}
//通过Proxy类利用反射机制创建了这个代理类
public Object create(){
return Proxy.newProxyInstance(getClass().getClassLoader(),obj.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
eatbefore();
Object invoke = method.invoke(obj, args);
eatafter();
return invoke;
}
//增强方法
private void eatafter() {
System.out.println("去洗碗筷!!");
}
private void eatbefore() {
System.out.println("先洗手!!");
}
}
cglib动态代理
用它就可以实现代理没有实现接口的类,其原理就是继承被代理类然后生成被代理类的子类,最终增强方法。既然是继承类实现的话,就不适用与final修饰类的情况,因为无法继承。
废话不多说,看实现。。。
实现
现在没有”吃“这个接口了,我们可以直接代理Eat类:
public class Ea{
public void eat() {
System.out.println("我要吃!!!");
}
}
public class CglibProxy implements MethodInterceptor {
private Object obj;
public CglibProxy(Object obj){
this.obj=obj;
}
//通过Enhancer类生成被代理类的子类
public Object create(){
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(obj.getClass());
//设置回调,当调用方法时,回调重写的intercept方法
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
eatbefore();
Object invoke = method.invoke(obj, objects);
eatafter();
return invoke;
}
private void eatafter() {
System.out.println("去洗碗筷!!");
}
private void eatbefore() {
System.out.println("先洗手!!");
}
}