代理模式

  1. 什么是代理模式
    代理模式也叫做委托模式,是结构性模式之一。在某些情况下,一个对象不方便或不能直接被另外一个直接引用,所以就出现了代理对象,由代理对象引用其本对象。就比如现实生活中的邮局、快递公司、婚介所等等

  2. 代理对象的分类
    代理对象分为静态代理和动态代理
    静态代理:是由程序员通过java代码创建或某些工具自动生成源代码,经过编译生成.class字节码文件,在程序运行之前就被创建好了。
    动态代理:通过反射动态创建。

  3. 代理模式的优缺点
    优点

    1. 降低耦合度,扩展性好
    2. 保护了目标对象
    3. 在原来的基础上增强了目标类
    

    缺点

    1. 增加了很多的类
    2. 由于增加了增强方法,会使访问数度变慢
    3. 增加了系统的复杂度(不过好的框架怎是有优缺点的,比如Spring)
    
  4. 静态代理类
    我创建一个BaseService接口,这里面有eat();和toilet()这两个方法。在代理类中对这两个类进行前置和后置增强。

    BaseService.java
    
public interface BaseService {
    void eat();

    void toilet();
}
Person.java
public class Person implements BaseService {
    public void eat() {
        System.out.println("吃饭了!");
    }

    public void toilet() {
        System.out.println("上厕所!");
    }
}
PersonProxy.java
public class PersonProxy implements BaseService {

    private Person person;

    public PersonProxy(Person person){
        this.person=person;
    }
    //吃饭方法
    public void eat() {
        before("eat");
        person.eat();
        after("eat");
    }

    //上厕所方法
    public void toilet() {
        before("toilet");
        person.toilet();
        after("toilet");
    }
	//前置增强
    private void before(String name){
        if (name.equals("toilet")){
            System.out.println("记得拿纸!!!");
        }else if (name.equals("eat")){
            System.out.println("吃饭之前先洗手");
        }
    }
	//后置增强
    private void after(String name){
        if (name.equals("toilet")){
            System.out.println("记得洗手!!!");
        }else if (name.equals("eat")){
            System.out.println("饭后一杯茶");
        }
    }
}

TestMain.java
public class TestMain {
    public static void main(String[] args) {
        Person p=new Person();
        //代理类
        PersonProxy pp=new PersonProxy(p);

        pp.eat();

        pp.toilet();
    }
}
吃饭之前先洗手
吃饭了!
饭后一杯茶

记得拿纸!!!
上厕所!
记得洗手!!!
  1. 动态代理
    BaseService.java
public interface BaseService {
    void eat();

    void toilet();
}
Person.java
public class Person implements BaseService {
    public void eat() {
        System.out.println("吃饭了!");
    }

    public void toilet() {
        System.out.println("上厕所!");
    }
}
Invocation.java   动态代理类
public class Invocation implements InvocationHandler {

    private Object obj;

    public  Object getInstance(Object obj){
        this.obj=obj;
        Class clazz=this.obj.getClass();
        return Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this);
    }
	//动态代理
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        before(method.getName());
        method.invoke(this.obj,args);
        after(method.getName());
        return null;
    }
	//前置增强
    private void before(String name){
        if (name.equals("toilet")){
            System.out.println("记得拿纸!!!");
        }else if (name.equals("eat")){
            System.out.println("吃饭之前先洗手");
        }
    }
	//后置增强
    private void after(String name){
        if (name.equals("toilet")){
            System.out.println("记得洗手!!!");
        }else if (name.equals("eat")){
            System.out.println("饭后一杯茶");
        }
    }
}

TestMain.java
public class TestMain {
    public static void main(String[] args) {
        Person p=new Person();
        //代理类
        PersonProxy pp=new PersonProxy(p);

        pp.eat();

        pp.toilet();
    }
}
吃饭之前先洗手
吃饭了!
饭后一杯茶

记得拿纸!!!
上厕所!
记得洗手!!!

Cglib动态代理

//引入jar包:
<dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.3.0</version>
        </dependency>
    </dependencies>
public class CglibProxy implements MethodInterceptor {

    public Object getInstance(Class clazz){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);

        return enhancer.create();
    }


    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before(method.getName());
        Object obj= methodProxy.invokeSuper(o,objects);
        after(method.getName());
        return obj;
    }


    private void before(String name){
        if (name.equals("toilet")){
            System.out.println("记得拿纸!!!");
        }else if (name.equals("eat")){
            System.out.println("吃饭之前先洗手");
        }
    }

    private void after(String name){
        if (name.equals("toilet")){
            System.out.println("记得洗手!!!");
        }else if (name.equals("eat")){
            System.out.println("饭后一杯茶");
        }
    }
}

结果是一样的

  1. JDK和CGLIB动态代理对比

    1.JDK 动态代理是实现了被代理对象的接口,CGLib 是继承了被代理对象。
    2.JDK 和 CGLib 都是在运行期生成字节码,JDK 是直接写 Class 字节码,CGLib 使用 ASM框架生成	
    Class 字节码,Cglib 代理实现更复杂,生成代理类比 JDK 效率低。
    3.JDK 调用代理方法,是通过反射机制调用,CGLib 是通过 FastClass 机制直接调用方法,CGLib执行效率更高。
    
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值