代理模式之动态代理模式

6 篇文章 0 订阅

动态代理模式



一、动态代理

概念:程序运行的时候,根据要被代理的对象动态生成代理类(代理类不需要程序员自己去编写,由系统提供,
只需要关注业务方法的功能增强(处理))。
动态代理的分类:jdk动态代理和cglib动态代理。

1. jdk动态代理

jdk动态代理要求目标对象必须要实现接口。
其中有一个方法很重要
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h){
}

该方法可以为任何实现了该接口的对象提供代理对象,而且可以针对目标对象实现接口中的方法进行增强。
其中public interface InvocationHandler {
public Object invoke(Object proxy,Method method Object[] args)
throws Throwable;
}

method:指代目标对象接口中的方法,使用的时候,往往method.invoke(目标对象,参数)该方法中的invoke方法很重要。
public Object invoke(Object obj, Object… args)
obj====》调用当前对象的方法。
args===》参数

2.cglib动态代理

cglib动态代理:cglib代理生成目的对象的子类对象(底层在内存中生成了该目标对象的子类对象),会对目标对象中的所有方法都进行增强(处理),
cglib代理称为子类代理。
注意:要想使用cglib的话需要导入第三方jar包。
1 特点:目标对象不需要实现接口,就可以提供其代理对象
注意:对特殊方法(final),无法处理。

2 hibernate和spring底层广泛的使用到了cglib代理,但是面试的时候,一般问jdk为主。

3 核心方法功能:
Enhancer:核心类,提供目标对象的子类对象(代理对象)===》相当于Proxy
create():提供代理对象 ====》相当于newProxyInstance
MethodInterceptor:接口
intercept:抽象方法,对目标对象方法的增强

二、jdk代理模式代码

1.aop切面实体类

代码如下(示例):

public class TranAop {
    public void before(){
        System.out.println("开启事务");
    }
    public void after(){
        System.out.println("提交事务");
    }
    public void exception(){
        System.out.println("回滚事务");
    }
    public void myFinally(){
        System.out.println("最终的操作");
    }
}

2.接口

代码如下(示例):

//创建三个方法一个是修改,添加,查询。
public interface UserService {
    void updateUser();
    void insertUser(String name);
    String findUserById(int id);
}

3.目标对象

public class UserServiceIpml implements UserService{
    @Override
    public void updateUser() {
        System.out.println("修改操作");
    }

    @Override
    public void insertUser(String name) {
        System.out.println("插入操作:"+name);
    }

    @Override
    public String findUserById(int id) {
        System.out.println("查询操作");
        return "user:"+id;
    }

动态代理模式

public class jdkProxyFactory {
    //先引入两个实体对象
    private TranAop tranAop;
    private UserService userService;

    //注入目标对象
    public jdkProxyFactory(TranAop tranAop, UserService userService) {
        this.tranAop = tranAop;
        this.userService = userService;
    }
    //工厂方法:提供代理对象
    public Object getProxyFactory(){
        return Proxy.newProxyInstance(userService.getClass().getClassLoader(),
                //目标对象实现的接口
                userService.getClass().getInterfaces(),
                //回调函数只需要调用其中的invoke方法就可以其他不需要
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        Object obj=null;
                        if(method.getName().startsWith("find")){
                            obj=method.invoke(userService,args);
                            return obj;
                        }
                                try{
                                    tranAop.before();
                                 Object result= method.invoke(userService,args);//相当于此处调用目标对象 args:它会自动选择对象方法的参数
                                    tranAop.after();
                                    return result;
                                }catch (Exception e){
                                    tranAop.exception();
                                    throw  e;
                                }finally {
                                    tranAop.myFinally();
                                }
                    }
                }
        );
    }
}

测试类

public class AppTest {
@Test
    public void test1(){
       TranAop tranAop = new TranAop();
       UserServiceIpml userServiceIpml = new UserServiceIpml();
       UserService userService = (UserService) new jdkProxyFactory(tranAop,userServiceIpml).getProxyFactory();
      userService.insertUser("周止若");
      userService.updateUser();
      userService.findUserById(100);
   }
}   

三、cglib代理对象代码

目标对象

public class EmpService {
    public void updateEmp(String name){
        System.out.println("修改操作");
    }
    public void deleteEmp(int id){
        System.out.println("删除操作");
    }

cglib代理对象

public class cglibProxyFactory {
    private TranAop tranAop;
    private EmpService empService;

    public cglibProxyFactory(TranAop tranAop, EmpService empService) {
        this.tranAop = tranAop;
        this.empService = empService;
    }
    public Object getCglibProxyFactory(){
        return Enhancer.create(empService.getClass(),
                new MethodInterceptor() {
                    @Override
                        public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
                        try {
                            tranAop.before();
                            Object result = methodProxy.invokeSuper(o,objects);
                            tranAop.after();
                            return result;
                        }catch(Exception e){
                            tranAop.exception();
                            throw e;
                        }finally{
                            tranAop.myFinally();
                        }
                    }
                }
        );
    }
}

测试类

public class AppTest 
{
@Test
    public void test04(){
        TranAop aop = new TranAop();
        EmpService empService = new EmpService();
        EmpService empService2 = (EmpService) new cglibProxyFactory(aop,empService).getCglibProxyFactory();
        empService2.updateEmp("刘诗诗");
        empService2.deleteEmp(3);
    }
}

总结

jdk动态代理模式相对于cglib动态代理模式在运用上两者也不想上下,不过用jdk代理模式的还是相对于多一些。
静态代理模式和动态代理模式相比较来说的话动态代理模式应用更广泛,更灵活。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值