java中的代理

java中的代理作用:降低代码的冗余

分类:

1.静态代理

2.jdk动态代理

3.cglib动态代理

首先放上基础代码:

package com.esx.bean;
/**
 * 性别
 * @author 二师兄
 *
 */
public enum Agen {
WOMAN,MAN

}

package com.esx.bean;


public class User {
    private String username;
    private String userpassword;
    private Agen gender;
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getUserpassword() {
return userpassword;
}
public void setUserpassword(String userpassword) {
this.userpassword = userpassword;
}
public Agen getGender() {
return gender;
}
public void setGender(Agen gender) {
this.gender = gender;
}
public User(String username, String userpassword, Agen gender) {
this.username = username;
this.userpassword = userpassword;
this.gender = gender;
}
@Override
public String toString() {
return "User [username=" + username + ", userpassword=" + userpassword + ", gender=" + gender + "]";
}
    

}

package com.esx.dao.impl;
/**
 * 无实现类的
 * @author 二师兄
 *
 */
public class NoImplUserDao {
    public void add() {
    System.out.println("无实现类的userdao执行数据库Add方法.......");
    }

}

package com.esx.dao.impl;


import com.esx.bean.Agen;
import com.esx.bean.User;
import com.esx.dao.IUserdao;


public class UserDao implements IUserdao{
User user=new User("张三", "123456", Agen.MAN);
@Override
public void save() {
System.out.println(user.toString());
}
@Override
public void get() {
System.out.println(user.getUsername());
}

}


package com.esx.dao;


public interface IUserdao {
    public void save();
    public void get();

}

package com.esx.test;

import com.esx.dao.IUserdao;

/**
 * 静态代理
 * @author 二师兄
 *
 */
public class StaticProxy implements IUserdao{
private IUserdao target;
public StaticProxy(IUserdao target) {
this.target=target;
}
@Override
public void save() {
long stime=System.currentTimeMillis();
target.save();
long etime=System.currentTimeMillis();
System.out.println("这个程序共执行了"+(etime-stime)+"毫秒");
}
@Override
public void get() {
System.out.println("静态代理类执行");
target.get();
}

}

package com.esx.test;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * jdk 动态代理
 * @author 二师兄
 *
 */
public class DynamicProxy implements InvocationHandler {
    private Object target;
    /*public DynamicProxy(Object target) {
    this.target=target;
}*/
    public Object getDynamicProxyTargetInstance(Object target) {
    this.target=target;
    return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
    target.getClass().getInterfaces(), this);
    }
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

    Object returnValue=null;

             System.out.println("jdk动态代理==================================");

System.out.println("before calling :"+method);
    if("save".equals(method.getName())) {
      method.invoke(target, args);
    }
    System.out.println("after calling :"+method);
return returnValue;
}

}

jdk动态代理是通过实现java中的InvocationHandler  通过反射的方式来进行方法的调用

通过类的加载器将实际代理类和抽象代理类加载,再通过InvocationHandler  监听类中的方法调用,这时我们可以通过方法的名字进行过滤一般的只代理特定的方法

jdk动态代理有一个弊端:就是实际代理的类必须实现一个接口;因此cglib就完美的解决了这个弊端

package com.esx.test;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
 * 
 * @author 二师兄
 * cglib动态代理
 */
public class CglibProxy implements MethodInterceptor {
private Object target; 
public Object getCglibTargetProxyInstance(Object target) {
this.target=target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

                System.out.println("cglib动态代理===============================");

System.out.println("method run before。。。。。");
Object returnValue = proxy.invokeSuper(obj, args);
System.out.println("method run after...........");
return returnValue; 
}

}

//cglib代理并不是java自身的,因此需要导入其他cglib的jar包,但是这里还是需要导入另一个asm的jar包,如果没有这个包就会报这样的错误。

java中的代理_第1张图片

因为cglib的底层使用到了asm来获取实例对象。cglib是通过实现一个拦截器来实现代理 MethodInterceptor将嗦需要代理的类进行拦截,然后创造出其代理类的子对象,然后对这个生成的代理类进行方法拦截,判断是否有这个方法的名字【还是使用method.getname()来获取方法的名字】,有就执行。cglib进行代理的时候不要求类必须实现接口,    这里虽然看起来和jdk不一样,但是楼主认为还是一样的,jdk动态代理是具有现有的接口和实现类,而cglib是通过将代理的类创造出一个实现它的子类来实现代理。但是这样使得cglib使用范围更为宽泛   比如spring中的AOP编程,但是cglib有个限制,不能代理呗final修饰的类,为什么呢?final类是最终的类,不能被实现或者继承,因此cglib是无法为其造出子类。

package com.esx.test;

import org.junit.Test;
import com.esx.dao.IUserdao;
import com.esx.dao.impl.NoImplUserDao;
import com.esx.dao.impl.UserDao;


public class TestProxy {
/**
* 测试cglib代理
* @throws Exception
*/
@Test
public void testCglibProxy() throws Exception {

CglibProxy proxy = new CglibProxy();
// 有实现类的
IUserdao userdao = (IUserdao) proxy.getCglibTargetProxyInstance(new UserDao());
userdao.save();
userdao.get();
// 无实现类的
NoImplUserDao userdao1=(NoImplUserDao) proxy.getCglibTargetProxyInstance(new NoImplUserDao());
userdao1.add();
}
/**
* 测试jdk动态代理
* @throws Exception
*/
@Test
public void testDynamicProxy() throws Exception {
IUserdao userdao = (IUserdao) new DynamicProxy().getDynamicProxyTargetInstance(new UserDao());
userdao.save();
userdao.get();
}
/**
* 测试静态代理
* @throws Exception
*/
@Test
public void testStaticProxy() throws Exception {
IUserdao proxy = new StaticProxy(new UserDao());
proxy.save();
proxy.get();
}

}

以上的执行结果

java中的代理_第2张图片

   asm-all-3.3.1.jar:https://mvnrepository.com/artifact/asm/asm-all/3.3.1
   cglib-2.2.2.jar:https://mvnrepository.com/artifact/cglib/cglib/2.2.2

你可能感兴趣的:(JAVA学习)