02蚂蚁-设计模式——3.代理模式

代理模式

代理设计模式:通过代理控制对象的访问,可以详细访问某个对象的方法,在这个方法调用之前或调用后进行处理。既(AOP微实现),AOP核心技术面向切面编程。
静态代理和动态代理

静态代理(一般不用)
package mayi02.may02.proxy;

public interface UserDao {
    void userAdd();
}

package mayi02.may02.proxy;

public class UserDaoImpl implements UserDao {
    @Override
    public void userAdd() {
        System.out.println("新增用户");
    }
}

package mayi02.may02.proxy;

//静态代理,静态代理需要生产代理对象
public class UserDaoProxy implements UserDao {
    UserDao userDao;
    UserDaoProxy(UserDao userDao){
        this.userDao = userDao;
    }

    @Override
    public void userAdd() {
        System.out.println("开启事务");
        userDao.userAdd();
        System.out.println("关闭事务");
    }
}

package mayi02.may02.proxy;

public class Client {
    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        UserDaoProxy userDaoProxy =  new UserDaoProxy(userDao);
        userDaoProxy.userAdd();
    }
}

动态代理
  1. jdk动态代理
    原理:是根据类加载器和接口创建代理类(此代理类是接口的实现类,所以必须使用接口 面向接口生产代理,位于java.lang.reflect包下)
  2. cglib动态代理
    原理:利用asm开源包,对代理对象的类的class文件加载进来,通过修改器字节码生成字类来处理。

jdk动态代理实例
userDao 是用是上面的userDao必须要有目标代理对象,目标代理对象必须要有接口

package mayi02.may02.jdkproxy;

import mayi02.may02.proxy.UserDao;
import mayi02.may02.proxy.UserDaoImpl;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//每次生成动态代理对象时,实现了Invocationhandler接口的调用处理器对象
public class InvocationHandlerImpl implements InvocationHandler {
    private Object target;//目标代理对象
    public InvocationHandlerImpl(Object target){
        this.target = target;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //开启事务
        System.out.println("动态代理-开启事务");
        Object invok = method.invoke(target,args);
        System.out.println("动态代理-提交事务");
        return invok;
    }

    public static void main(String[] args) {
        UserDao userDao = new UserDaoImpl();
        InvocationHandlerImpl invocationHandlerImpl = new InvocationHandlerImpl(userDao);
        //获取类加载器
        ClassLoader classLoader = userDao.getClass().getClassLoader();
        //获取当前类的接口
        Class<?>[] interfaces = userDao.getClass().getInterfaces();
        //调用动态代理实例
        UserDao userDao1 = (UserDao) Proxy.newProxyInstance(classLoader,interfaces,invocationHandlerImpl);
        userDao1.userAdd();
    }
}

cglib动态代理

同样需要代理对象,但是代理对象不一定要实现接口

package mayi02.may02.cglib;

import mayi02.may02.proxy.UserDaoImpl;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class CglibProxy implements MethodInterceptor {
    private Object targetObject;
    public Object getInstance(Object targetObject){
        this.targetObject = targetObject;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(targetObject.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("开启事务");
        Object invoke = proxy.invoke(targetObject,args);
        System.out.println("提交事务");
        return invoke;
    }

    public static void main(String[] args) {
        CglibProxy cglibProxy = new CglibProxy();
        UserDaoImpl userDaoImpl = (UserDaoImpl) cglibProxy.getInstance(new UserDaoImpl());
        userDaoImpl.userAdd();
    }
}

总结:
1.CGLIB 没有依赖接口 字节码ASM
2.jdk 反射技术

CGLIB动态代理与JDK动态区别

java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
Spring中。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
JDK动态代理只能对实现了接口的类生成代理,而不能针对类 。
CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法 。
因为是继承,所以该类或方法最好不要声明成final ,final可以阻止继承和多态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值