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动态代理==================================");
}
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动态代理===============================");
}
//cglib代理并不是java自身的,因此需要导入其他cglib的jar包,但是这里还是需要导入另一个asm的jar包,如果没有这个包就会报这样的错误。
因为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();
}
}
以上的执行结果
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