java随记

动态代理

实例参考SSM-Mybatis注解使用

  1. JDK动态代理原理
  • 创建一个继承Proxy和实现被代理对象的接口的新类,在每次调用方法的时候都会调用invoke
  • 它需要三个参数,前两个参数的意思是在同一个classloader下通过接口创建出一个对象,该对象需要一个属性,也就是第三个参数,它是一个InvocationHandler,每次调用会执行InvocationHandler的invoke方法
  • 这里可以看出代理类实现newProxyInstance的第二个参数interfaces的所有接口,所以只能强转成其中的接口
    • 如果只希望产生接口的代理可以使用new Class[]{BookMapper.class}
    • 如过要产生实现类的代理使用class.getInterfaces()即可
    public final class XXX extends Proxy implements XXX
    public final String SayHello(String paramString)
     {
    try
    {
      return (String)this.h.invoke(this, m4, new Object[] { paramString });
    }
    catch (Error|RuntimeException localError)
    {
      throw localError;
    }
    catch (Throwable localThrowable)
    {
      throw new UndeclaredThrowableException(localThrowable);
    }
    
  1. cglib动态代理
    cglib的原理是这样,它生成一个继承B的类型C(代理类),这个代理类持有一个MethodInterceptor,我们setCallback时传入的。 C重写所有B中的方法(方法名一致),然后在C中,构建名叫“CGLIB”+“$父类方法名$”的方法(下面叫cglib方法,所有非private的方法都会被构建),方法体里只有一句话super.方法名(),可以简单的认为保持了对父类方法的一个引用,方便调用
    public class CglibProxy implements MethodInterceptor
    {
        // 根据一个类型产生代理类,此方法不要求一定放在MethodInterceptor中
        public Object CreatProxyedObj(Class<?> clazz)
        {
            Enhancer enhancer = new Enhancer();
            
            enhancer.setSuperclass(clazz); // 因为是生成子类所以必须指定父类
            
            enhancer.setCallback(this); // 执行intercept方法的回调
            
            return enhancer.create();
        }
        
        @Override
        public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable
        {
            // 这里增强
            System.out.println("收钱");
            
            return arg3.invokeSuper(arg0, arg2);
        } 
    }
    
    自定义工具类
    	public class MyProxy implements InvocationHandler {
        private Invoke invoke;
        public MyProxy(Invoke invoke) {
            this.invoke = invoke;
        }
        private MyProxy() {}
        //
        public <T> T getProxy(Class<? extends T> target){
            return (T) Proxy.newProxyInstance(this.getClass().getClassLoader(),
                    target.getInterfaces(), this);
        }
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            return invoke.run(method, args);
        }
        public interface Invoke{
             Object run(Method method, Object[] args) throws Throwable;
        }
    }
    -- 使用
    B b = new B();
    MyProxy proxy = new MyProxy((method, args) -> {
         System.out.println("pre");
         method.invoke(b,args);
         System.out.println("after");
         return null;
     });
     A a = proxy.getProxy(B.class);
     a.show();
    

ThreadLocal

  1. 每个Thread维护着一个ThreadLocalMap的引用

  2. ThreadLocalMap是ThreadLocal的内部类,用Entry来进行存储

  3. ThreadLocal创建的副本是存储在自己的threadLocals中的,也就是自己的ThreadLocalMap。

  4. ThreadLocalMap的键值为ThreadLocal对象,而且可以有多个threadLocal变量,因此保存在map中

  5. 在进行get之前,必须先set,否则会报空指针异常,当然也可以初始化一个,但是必须重写initialValue()方法。

  6. ThreadLocal本身并不存储值,它只是作为一个key来让线程从ThreadLocalMap获取value。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

信息技术王凤龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值