浅谈Java代理(jdk静态代理、动态代理和cglib动态代理)
|
一、代理是Java常用的设计模式,代理类通过调用被代理类的相关方法,并对相关方法进行增强。加入一些非业务性代码,比如事务、日志、报警发邮件等操作。 二、jdk静态代理 1、业务接口
/**
* 业务接口
* @author pc
*
*/
public interface UserService {
// 增加一个用户
public void addUser();
// 编辑账户
public void editUser();
}
2、业务实现类
/**
* 业务实现类
* @author pc
*
*/
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("增加一个用户。。。");
}
public void editUser() {
System.out.println("编辑一个用户。。。");
}
}
3、代理类 /** 4、测试类
public static void main(String[] args) {
UserServiceImpl userImpl = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy(userImpl);
proxy.addUser();
System.out.println("----------分割线----------");
proxy.editUser();
}
5、结果 代理类方法,进行了增强。。。 事务开始。。。 ----------分割线---------- 代理类方法,进行了增强。。。 三、jdk动态代理 1、业务接口
/**
* 业务接口
* @author pc
*
*/
public interface UserService {
// 增加一个用户
public void addUser();
// 编辑账户
public void editUser();
}
2、业务接口实现类
/**
* 业务接口实现类
* @author pc
*
*/
public class UserServiceImpl implements UserService {
public void addUser() {
System.out.println("增加一个用户。。。");
}
public void editUser() {
System.out.println("编辑一个用户。。。");
}
}
3、代理类
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
*
* @author pc
*
*/
public class ServiceInvocationHandler implements InvocationHandler {
// 目标对象
private Object target;
public ServiceInvocationHandler(Object target) {
super();
this.target = target;
}
/**
* 创建代理实例
* @return
* @throws Throwable
*/
public Object getProxy() throws Throwable {
return Proxy.newProxyInstance(Thread.currentThread()
.getContextClassLoader(),this.target.getClass()
.getInterfaces(),this);
// 这样写只返回了目标对象,没有生成代理对象。
// return target;
}
/**
* 实现InvocationHandler接口方法
* 执行目标对象的方法,并进行增强
*/
public Object invoke(Object proxy,Method method,Object[] args)
throws Throwable {
Object result = null;
System.out.println("代理类方法,进行了增强。。。");
System.out.println("事务开始。。。");
// 执行目标方法对象
result = method.invoke(target,args);
System.out.println("事务结束。。。");
return result;
}
}
4、测试类
public class Test {
/**
* jdk动态代理会生成一个动态代理类,生成相应的字节码,然后通过ClassLoader加载字节码。
* 该实例继承了Proxy类,并实现了业务接口,在实现的方法里通过反射调用了InvocationHandler接口实现类
* 的invoke()回调方法。
* @param args
* @throws Throwable
*/
public static void main(String[] args) throws Throwable {
UserService userService = new UserServiceImpl();
ServiceInvocationHandler handler = new ServiceInvocationHandler(userService);
// 根据目标生成代理对象
UserService proxy = (UserService) handler.getProxy();
proxy.addUser();
// proxy.editUser();
}
}
5、测试结果 代理类方法,进行了增强。。。 四、cglib动态代理 需要引入cglib的jar包, 在pom.xml加入依赖: <!-- https://mvnrepository.com/artifact/cglib/cglib --> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>2.2.2</version> </dependency>
1、业务类,没有实现接口
/**
* 业务类
* 没有实现接口
* 如果类是final的,则没法生成代理对象,报错。
* 如果方法是final的,代理无效
* @author pc
*
*/
public class UserServiceImpl {
public void addUser() {
System.out.println("增加一个用户。。。");
}
public void editUser() {
System.out.println("编辑一个用户。。。");
}
}
2、代理类
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
/**
* 使用Cglib动态代理
* @author pc
*
*/
public class UserServiceCglib implements MethodInterceptor{
private Object target;
/**
* 创建代理实例
* @param target
* @return
*/
public Object getInstance(Object target){
this.target = target;
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(this.target.getClass());
// 设置回调方法
enhancer.setCallback(this);
// 创建代理对象
return enhancer.create();
}
/**
* 实现MethodInterceptor接口要重写的方法。
* 回调方法
*/
public Object intercept(Object obj,Object[] args,MethodProxy proxy) throws Throwable {
System.out.println("事务开始。。。");
Object result = proxy.invokeSuper(obj,args);
System.out.println("事务结束。。。");
return result;
}
}
3、测试类
public class TestCglib {
public static void main(String[] args) {
UserServiceCglib cglib = new UserServiceCglib();
UserServiceImpl bookFacadeImpl = (UserServiceImpl)cglib.getInstance(new UserServiceImpl());
bookFacadeImpl.addUser();
// bookFacadeImpl.editUser();
}
}
4、结果: 事务开始。。。 5、如果业务实现类被定义成final类,就会报以下错误 Exception in thread "main" java.lang.IllegalArgumentException: Cannot subclass final class class cn.xx.xx.cgilb.UserServiceImpl at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:446) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:285) at cn.pconline.proxy.cgilb.UserServiceCglib.getInstance(UserServiceCglib.java:30) at cn.pconline.proxy.cgilb.TestCglib.main(TestCglib.java:7) 五、总结 1、原理 jdk静态代理实现比较简单,一般是直接代理对象直接包装了被代理对象。 jdk动态代理是接口代理,被代理类A需要实现业务接口,业务代理类B需要实现InvocationHandler接口。 jdk动态代理会根据被代理对象生成一个继承了Proxy类,并实现了该业务接口的jdk代理类,该类的字节码会被传进去的ClassLoader加载,创建了jdk代理对象实例, (编辑:安卓应用网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- java 发送带Basic Auth认证的http post请求实例代码
- java – Eclipse自动完成不适用于lambda和类型
- 添加另一个对象时java.util.ConcurrentModificationExcepti
- java – hashCode实现策略
- java – 握手失败 – 在Intellij中调试Solr时连接超自然关闭
- Java Web应用程序具有Paypal集成
- 简单Ehcahe封装
- Android的Volley网络Get/Post请求包实例代码
- java – 从map中键入不匹配的键:expected .. Text,receive
- JavaFX – 如何创建SnapShot /(invisble)WebView的屏幕截图
