【javaSE】代理并不难

2023-12-31 23:33:05

代理:

代理模式最主要的就是在不改变原来代码(就是目标对象)的情况下实现功能的增强

在学习AOP之前先了解代理,代理有两种:一种是动态代理,一类是静态代理。

静态代理

????????相当于是自己写了一个代理类,在调用的时候调用的是代理类,代理类中的处理还是原生的处理逻辑,不过在前后添加上需要增强功能的代码。(类似继承实现的)

缺点:需要为每一个被代理的对象都创建一个代理类。

静态代理实现:

1.创建接口

public interface Target {
    public abstract String getExe();
}

2.实现目标对象

public class MyTarget implements Target {


    @Override
    public String getExe() {
        System.out.println("执行ing.....");
        return "ok";
    }
}

3.实现代理对象

package 反射;

public class Proxy implements Target{

    MyTarget myTarget;

    public Proxy(MyTarget myTarget) {
        this.myTarget = myTarget;
    }

    @Override
    public String getExe() {
        System.out.println("权限检查");
        String res= myTarget.getExe();
        System.out.println("日志打印");

        return res;

    }
}

4.测试代码

package 反射;


public class demo1 {

    public static void main(String[] args) {
        MyTarget myTarget=new MyTarget();
        Proxy proxy = new Proxy(myTarget);
        proxy.getExe();
    }


}

?

动态代理

动态代理模式最大的优势就是不用自己去写一个代理对象,它的代理对象会在java文件编译的时候,通过Java反射去创建的。所以减少了程序员的工作。动态代理的实现有两种方式,现在来介绍一下(基于接口实现)

jdk代理

1.创建接口

package com.aqiuo.jdk;

public interface UserDao {
        public void addUser();
        public void deleteUser();
}

2.创建实现类

package 代理;

public class UserServiceImpl implements UserService{

    public void addUser(){
        System.out.println("添加用户");
    }
    public void delUser(){
        System.out.println("删除用户");
    }

}

3.编写切面类

package 代理;

public class Aspect {
    public void admission(){
        System.out.println("权限检查");
    }
    public void log(){
        System.out.println("日志打印");
    }
}

4.编写代理类

package 代理;

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

public class JdkProxy implements InvocationHandler {
    //用Object型才能动态代理
    Object object;

    public Object createInstance(Object object){
        this.object=object;
        Class[] clazz = object.getClass().getInterfaces();
        ClassLoader classLoader=JdkProxy.class.getClassLoader();
        return Proxy.newProxyInstance(classLoader,clazz,this);

    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Aspect aspect=new Aspect();
        aspect.admission();
        Object res= method.invoke(object,args);
        aspect.log();

        return res;
    }
}

5.测试:

public class Test {
    public static void main(String[] args) {
        JdkProxy jdkProxy =new JdkProxy();
        UserService userService=new UserServiceImpl();
        UserService proxy= (UserService) jdkProxy.createInstance(userService);
        proxy.addUser();;
        proxy.delUser();

    }
}

/**JDK代理有一定局限性,使用动态代理的对象必须实现一个或多个接口,如果要对没有实现接口的类进行代理,可以用CGLIB代理

CGLIB代理

CGLIB是一个高性能的开源代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类增强,已经在Spring中集成

导包

<dependency>
    <groupId>cglib</groupId>
    <artifactId>cglib</artifactId>
    <version>2.2.2</version>
</dependency>

?MethodInterceptor拦截器
cglib的实现最重要的就是去实现这个MethodInterceptor接口来完成,就像jdk时候的InvocationHandler一样

package com.aqiuo.cglib;
//被代理的类
public class UserDao {
    
    public void addUser() {
        // TODO Auto-generated method stub
        System.out.println("添加用户");
    }

    public void deleteUser() {
        // TODO Auto-generated method stub
        System.out.println("删除用户");
    }

}

?实现代理类

//代理类
package com.aqiuo.cglib;

import java.lang.reflect.Method;

import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import com.aqiuo.Aspect.MyAspect;

public class CglibProxy implements MethodInterceptor {
    
    //代理方法
    public Object createProxy(Object target) {
        //创建一个动态类对象
        Enhancer enhancer=new Enhancer();
        //确定要增强的类,设置为她的父类
        enhancer.setSuperclass(target.getClass());
        //添加回调函数
        enhancer.setCallback(this);
        //返回创建的代理类
        
        return enhancer.create();
    }
    
    /**
     * ProxyCGlib根据指定的父类,生成代理对象
     * method拦截的方法
     * args拦截方法的参数数组
     * methodProxy方法的代理对象,用来执行父类方法
     */
    

    @Override
    public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
        //创建切面类对象
        MyAspect myAspect=new MyAspect();
        //前增强
        myAspect.check_permissions();
        //目标方法执行
        Object object=methodProxy.invokeSuper( proxy, args);
        //后增强
        myAspect.log();
        
        return object;
    }
    

}

????????cglib的原理就是在运行的时候,cglib会自动去生成一个子类,在子类里面去完成增强操作(就是拦截器里面),这里我们来验证cglib就用保存它的子类来查验,也就是将它自动生成的类放在一个指定路径下去看。?


//测试类
package com.aqiuo.cglib;



public class CglibTest {
    public static void main(String[] args) {
        UserDao userDao=new UserDao();
        CglibProxy proxy=new CglibProxy();
        UserDao userDao2=(UserDao) proxy.createProxy(userDao);
        userDao2.addUser();
        userDao2.deleteUser();
    }

}

cglib动态代理原理:
①创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器

②在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))

③创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))

④创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用

文章来源:https://blog.csdn.net/m0_62645012/article/details/135320390
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。