java动态代理(JDK和CGLIB)笔记

动态代理:为一堆interface或类的实现提供统一的执行通道,从含义上就像局域网电脑通过代理上网一样,走统一的通道,代理控制通道,自然可以在通道里加上自定义实现,例如像AOP切面,日志等。

JDK的动态代理只能对接口实现,代理类需要实现InvocationHandler 接口。

一、接口

public interface UserService {
    User addUser();
    void editUser(User user);
    int deleteUser(int userId);
}

//假设有这么一个User类
public class User {
    private Integer userId;
    private String userName;
    private String password;

    public Integer getUserId() {
        return userId;
    }

    public void setUserId(Integer userId) {
        this.userId = userId;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    @Override
    public String toString() {
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                ", password='" + password + '\'' +
                '}';
    }
}

 

二、接口的实现

public class UserServiceImpl implements UserService {
    @Override
    public User addUser() {
        User user = new User();
        user.setUserId(1);
        user.setUserName("userTest");
        user.setPassword("123456");
        System.out.println("------> add user");
        return user;
    }

    @Override
    public void editUser(User user) {
        System.out.println("------> edit user:" +user);
    }

    @Override
    public int deleteUser(int userId) {
        System.out.println("------> delete user:"+userId);
        return 1;
    }
}

 

三、JDK代理类实现InvocationHandler

public class ProxyHandler implements InvocationHandler {

    //被代理对象
    private Object proxied;

    public ProxyHandler(Object proxied) {
        this.proxied = proxied;
    }

    private void beforeInvoke(String msg)
    {
        System.out.println("-------> beforInvoke:"+msg);
    }

    private void afterInvoke(String msg)
    {
        System.out.println("-------> afterInvoke:"+msg);
    }

    private String convertArgs(Object[] args)
    {
        if(args==null || args.length==0)
        {
            return null;
        }
        StringBuilder sb= new StringBuilder();
        for(Object object : args)
        {
            sb.append(object.toString());
        }

        return sb.toString();
    }

    //proxy是代理对象,可以想象成代理服务器
    //proxied是被代理对象,可以想象成局域网里的PC
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        beforeInvoke("proxy name:"+proxy.getClass().getName());
        beforeInvoke("proxied name:"+proxied.getClass().getName());
        beforeInvoke( "args:"+convertArgs(args));
        Object o = method.invoke(proxied,args);
        afterInvoke("result:"+o);
        return o;
    }
}

 

四、使用,实现原理是反射

public class Main {

    public static void main(String[] args) {
        UserService userService = new UserServiceImpl();
        UserService proxyUserService = (UserService) Proxy.newProxyInstance(
                UserService.class.getClassLoader(),
                new Class[]{UserService.class},
                new ProxyHandler(userService)
        );

        User user = proxyUserService.addUser();

        proxyUserService.editUser(user);

        proxyUserService.deleteUser(user.getUserId());

    }
}

 

五、结果:符合预期的输出

六、简化一下写法,代理类的生成方式

public class DynamicProxy implements InvocationHandler {
    private Object proxied;

    private void beforeInvoke(String msg)
    {
        System.out.println("-------> beforInvoke:"+msg);
    }

    private void afterInvoke(String msg)
    {
        System.out.println("-------> afterInvoke:"+msg);
    }

    private String convertArgs(Object[] args)
    {
        if(args==null || args.length==0)
        {
            return null;
        }
        StringBuilder sb= new StringBuilder();
        for(Object object : args)
        {
            sb.append(object.toString());
        }

        return sb.toString();
    }

  //在这里就把代理对象创建出来 public Object getProxyObject(Object proxied) { this.proxied = proxied; return Proxy.newProxyInstance( this.proxied.getClass().getClassLoader(), this.proxied.getClass().getInterfaces(), this ); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { beforeInvoke("proxy name:"+proxy.getClass().getName()); beforeInvoke("proxied name:"+proxied.getClass().getName()); beforeInvoke( "args:"+convertArgs(args)); Object o = method.invoke(proxied,args); afterInvoke("result:"+o); return o; } } //main public class Main { public static void main(String[] args) { System.out.println("##############"); System.out.println("-------> second call:"); UserService userService = (UserService) new DynamicProxy().getProxyObject(new UserServiceImpl()); User user1 = userService.addUser(); userService.editUser(user1); userService.deleteUser(user1.getUserId()); } }

 

六、使用cglib动态代理

cglib可以代理非接口类,但是因为其实现原理是继承,所以无法代理被代理类中final方法,也无法代理final修饰的类。

代理类需要实现MethodInterceptor 接口

    <dependencies>
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.8</version>
        </dependency>

    </dependencies>

public class CglibDynamicProxy implements MethodInterceptor {
    private Object proxied;

    //Generate a new class if necessary and uses the specified callbacks (if any) to create a new object instance.
    //Uses the no-arg constructor of the superclass.
    //动态生成一个新的类,使用父类的无参构造方法创建一个指定了特定回调的代理实例
    public Object getProxyObject(Object proxied)
    {
        this.proxied = proxied;
        //增强器,动态代码生成器
        Enhancer enhancer = new Enhancer();
        //回调方法
        enhancer.setCallback(this);
        //设置生成类的父类类型
        enhancer.setSuperclass(proxied.getClass());
        //动态生成字节码并返回代理对象
        return enhancer.create();
    }

    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {

        beforeInvoke("Object:"+o.getClass().getName());
        beforeInvoke("method:"+method.getName());
        beforeInvoke("args:"+convertArgs(objects));
        beforeInvoke("methodProxy:"+methodProxy.getSignature());
        Object result = methodProxy.invoke(this.proxied,objects);
        afterInvoke("result:"+result);
        return result;
    }


    private void beforeInvoke(String msg)
    {
        System.out.println("-------> beforInvoke:"+msg);
    }

    private void afterInvoke(String msg)
    {
        System.out.println("-------> afterInvoke:"+msg);
    }

    private String convertArgs(Object[] args)
    {
        if(args==null || args.length==0)
        {
            return null;
        }
        StringBuilder sb= new StringBuilder();
        for(Object object : args)
        {
            sb.append(object.toString());
        }

        return sb.toString();
    }
}

main:

public class Main {

    public static void main(String[] args) {



        System.out.println("##############");

        System.out.println("-------> 4 call:");
        UserService service4 = (UserService)new CglibDynamicProxy().getProxyObject(new UserServiceImpl());
        User user4 = service4.addUser();
        service4.editUser(user4);
        service4.deleteUser(user4.getUserId());



    }
}

 

posted @ 2018-11-27 22:50  我是属车的  阅读(197)  评论(0编辑  收藏  举报