我们假设有下面一个场景:
假如一个项目做完上线了,代码如下所示。(简单的演示)
public interface UserService {
void add();
void delete();
void update();
void query();
}
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("执行了add方法");
}
public void delete() {
System.out.println("执行了delete方法");
}
public void update() {
System.out.println("执行了update方法");
}
public void query() {
System.out.println("执行了query方法");
}
}
客户端:
public class Client {
public static void main(String[] args) {
UserServiceImpl service = new UserServiceImpl();
service.add();
}
}
现在比如说这个项目运营了一段时间了,现在想要增加新的功能,就是在每个方法前加上打印日志的功能,我们如果在原代码上面加代码,有可能会把原项目搞崩的,所以我们就要用到一种模式叫代理模式!有静态代理和动态代理
稍微了解了下代理模式,接下来看实现:
静态代理:
我们代理了UserServiceImpl 这个类,类如下↓:
public class UserServiceImplProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
public void add() {
log("add");
userService.add();
}
public void delete() {
log("delete");
userService.delete();
}
public void update() {
log("update");
userService.update();
}
public void query() {
log("query");
userService.query();
}
//新的方法:打印日志
public void log(String msg){
System.out.println("打印"+msg+"日志");
}
}
客户端:
public class Client {
public static void main(String[] args) {
UserServiceImplProxy proxy = new UserServiceImplProxy();
proxy.setUserService(new UserServiceImpl());
proxy.add();
}
}
好处:这样子我们在不改动原来代码的情况下,增加了功能
缺点:一个真实角色就会产生一个代理角色,代码量翻倍
我们想要解决静态代理的缺点,就出现了动态代理↓
动态代理:
public interface UserService {
void add();
void delete();
void update();
void query();
}
public class UserServiceImpl implements UserService {
public void add() {
System.out.println("执行了add方法");
}
public void delete() {
System.out.println("执行了delete方法");
}
public void update() {
System.out.println("执行了update方法");
}
public void query() {
System.out.println("执行了query方法");
}
}
public class ProxyInvocationHandler implements InvocationHandler {
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),userService.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log();
Object result = method.invoke(userService, args);
return result;
}
public void log(){
System.out.println("打印日志");
}
}
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setUserService(userService);
UserService proxy = (UserService) pih.getProxy();
proxy.delete();
}
}
动态代理的好处:
- 静态代理的所有优点
- 动态代理的是一个接口,对应的一类业务
- 一个动态代理类可以代理多个类,只要这些类实现了同一个接口(target所属于的接口)
区别
静态代理,一个代理类只能代理一个真实对象。
动态代理,一个动态代理类能代理多个真实对象!!