一 代理模式简介
代理(Proxy)是一种设计模式 提供了对目标对象另外的访问方式
代理对象代理目标对象 达到增强目标对象功能的目的
二 静态代理
需要定义接口或者父类 代理对象与目标对象一起实现相同接口或者继承相同父类
优点: 在不修改目标对象的功能前提下 对目标功能扩展
缺点: 因为代理对象需要与目标对象一起实现相同接口或者继承相同父类 所以会有很多代理类 导致类太多 同时 如果接口增加方法 代理对象与目标对象都要维护
1. 接口
/**
* 接口
* Created by Hy on 2020/7/10.
*/
public interface IUserService {
void insertUser();
String deleteUser(int id);
}
2. 目标对象
/**
* 目标对象
* Created by Hy on 2020/7/10.
*/
public class UserService implements IUserService {
@Override
public void insertUser() {
System.out.println("insert ok");
}
@Override
public String deleteUser(int id) {
System.out.println("delete... ... ...");
return "id = " + id + " delete ok";
}
}
3. 代理对象
/**
* 代理对象
* Created by Hy on 2020/7/13.
*/
public class UserServiceProxy implements IUserService {
private IUserService target; //目标对象
public UserServiceProxy(IUserService target) {
this.target = target;
}
@Override
public void insertUser() {
System.out.println("增强方法体 1/2");
target.insertUser();
System.out.println("增强方法体 2/2");
}
@Override
public String deleteUser(int id) {
id++; //增强参数
String s = target.deleteUser(id);
s = s + "!!!"; //增强返回值
return s;
}
}
4. 测试
@Test
public void test01() {
// 创建目标对象
UserService target = new UserService();
// 创建代理对象
UserServiceProxy proxy = new UserServiceProxy(target);
// 使用代理对象调用方法
proxy.insertUser();
String s = proxy.deleteUser(1);
System.out.println(s);
}
三 动态代理(接口代理)
需要定义接口让目标对象实现 使用java.lang.reflect.Proxy动态的在内存中构建代理对象
优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象不需要实现接口
缺点: 目标对象一定要实现接口 否则不能用动态代理
1. 接口
/**
* 接口
* Created by Hy on 2020/7/10.
*/
public interface IUserService {
void insertUser();
String deleteUser(int id);
}
2. 目标对象
/**
* 目标对象
* Created by Hy on 2020/7/10.
*/
public class UserService implements IUserService {
@Override
public void insertUser() {
System.out.println("insert ok");
}
@Override
public String deleteUser(int id) {
System.out.println("delete... ... ...");
return "id = " + id + " delete ok";
}
}
3. 代理工厂
/**
* 代理工厂
* Created by Hy on 2020/7/13.
*/
public class ProxyFactory {
private Object target; //目标对象
public ProxyFactory(Object target) {
this.target = target;
}
public Object createProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
/**
* 代理对象调用的所有方法都会触发该方法执行
* @param proxy 代理对象
* @param method 被代理的方法
* @param args 被代理的方法传参
* @return 被代理的方法返回值
* @throws Throwable 异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("deleteUser".equals(method.getName())) {
// 增强指定方法
int id = (int) args[0];
id++; //增强参数
System.out.println("增强方法体 1/2");
String invoke = (String) method.invoke(target, id);
invoke = invoke + "!!!"; //增强返回值
System.out.println("增强方法体 2/2");
return invoke;
} else {
// 其它方法默认实现
Object invoke = method.invoke(target, args);
return invoke;
}
}
});
}
}
4. 测试
@Test
public void test01() {
// 创建目标对象
UserService target = new UserService();
System.out.println(target.getClass());
// 创建代理对象
IUserService proxy = (IUserService) new ProxyFactory(target).createProxyInstance();
System.out.println(proxy.getClass());
// 使用代理对象调用方法
proxy.insertUser();
String s = proxy.deleteUser(1);
System.out.println(s);
}
四 CGLIB代理(子类代理)
通过在内存中构建一个子类对象从而实现对目标对象功能的扩展 CGLIB是一个强大的高性能的代码生成包 底层使用一个小而快的字节码处理框架ASM来转换字节码并生成新的类
优点: 在不修改目标对象的功能前提下 对目标功能扩展 代理对象与目标对象都不需要实现接口
缺点: 需要引入CGLIB的JAR文件
1. 目标对象
/**
* 目标对象
* Created by Hy on 2020/7/10.
*/
public class UserService {
public void insertUser() {
System.out.println("insert ok");
}
public String deleteUser(int id) {
System.out.println("delete... ... ...");
return "id = " + id + " delete ok";
}
}
2. 代理工厂
/**
* 代理工厂
* Created by Hy on 2020/7/13.
*/
public class ProxyFactory {
private Object target; //目标对象
public ProxyFactory(Object target) {
this.target = target;
}
public Object createProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(new MethodInterceptor() {
/**
* 代理对象调用的所有方法都会触发该方法执行
* @param proxy 代理对象
* @param method 被代理的方法
* @param args 被代理的方法传参
* @param methodProxy 代理的方法
* @return 被代理的方法返回值
* @throws Throwable 异常
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if ("deleteUser".equals(method.getName())) {
// 增强指定方法
int id = (int) args[0];
id++; //增强参数
System.out.println("增强方法体 1/2");
String invoke = (String) method.invoke(target, id);
invoke = invoke + "!!!"; //增强返回值
System.out.println("增强方法体 2/2");
return invoke;
} else {
// 其它方法默认实现
Object invoke = methodProxy.invokeSuper(proxy, args); //等同 method.invoke(target, args);
return invoke;
}
}
});
return enhancer.create();
}
}
3. 测试
@Test
public void test01() {
// 创建目标对象
UserService target = new UserService();
System.out.println(target.getClass());
// 创建代理对象
UserService proxy = (UserService) new ProxyFactory(target).createProxyInstance();
System.out.println(proxy.getClass());
// 使用代理对象调用方法
proxy.insertUser();
String s = proxy.deleteUser(1);
System.out.println(s);
}
来源:oschina
链接:https://my.oschina.net/u/4271739/blog/4366086