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()); } }

猜你喜欢

转载自www.cnblogs.com/asker009/p/10029632.html
今日推荐