即Proxy Pattern,23种java常用设计模式之一。代理模式的定义:对其他对象提供一种代理以控制对这个对象的访问。
代理模式也是SpringAOP的底层
代理模式分类:
角色分析:
新建一个抽象角色类:Rent.java
package pers.mobian.proxy.demo1;
public interface Rent {
public void rent();
}
新建一个真实角色类:Host.java
package pers.mobian.proxy.demo1;
public class Host implements Rent {
@Override
public void rent() {
System.out.println("我是房东,我有房子出租");
}
}
新建一个代理角色类:Proxy.java
package pers.mobian.proxy.demo1;
public class Proxy implements Rent{
private Host host = new Host();
@Override
public void rent() {
seeHouse();
host.rent();
signContract();
}
private void seeHouse(){
System.out.println("中介带你看房子");
}
private void signContract(){
System.out.println("中介帮忙签合同");
}
}
新建一个用户测试类:User.java
package pers.mobian.proxy.demo1;
public class User {
public static void main(String[] args) {
Proxy proxy = new Proxy();
proxy.rent();
}
}
测试结果
中介带你看房子
我是房东,我有房子出租
中介帮忙签合同
代理模式的优点:
缺点:
角色分析:
抽象角色:UserService.java
package pers.mobian.proxy.demo2;
public interface UserService {
public void add();
public void delte();
public void update();
public void selet();
}
真实角色:UserServiceImpl.java
package pers.mobian.proxy.demo2;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("使用了增加方法");
}
@Override
public void delte() {
System.out.println("使用了删除方法");
}
@Override
public void update() {
System.out.println("使用了修改方法");
}
@Override
public void selet() {
System.out.println("使用了查找方法");
}
}
代理角色:Proxy.java
package pers.mobian.proxy.demo2;
public class Proxy implements UserService {
private UserServiceImpl userServiceImpl;
public void setUserServiceImpl(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
public Proxy(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
public Proxy() {
}
@Override
public void add() {
userServiceImpl.add();
show("add");
}
@Override
public void delte() {
userServiceImpl.delte();
show("delte");
}
@Override
public void update() {
userServiceImpl.update();
show("update");
}
@Override
public void selet() {
userServiceImpl.selet();
show("selet");
}
public void show(String method){
System.out.println(method+"方法使用成功");
}
}
客户:User.java
package pers.mobian.proxy.demo2;
public class User {
public static void main(String[] args) {
UserServiceImpl userServiceImpl = new UserServiceImpl();
Proxy proxy = new Proxy(userServiceImpl);
proxy.add();
proxy.delte();
proxy.selet();
proxy.update();
}
}
测试结果
使用了增加方法
add方法使用成功
使用了删除方法
delte方法使用成功
使用了查找方法
selet方法使用成功
使用了修改方法
update方法使用成功
实际开发中的模型(仅供参考)
需要了解两个类:Proxy:代理 , InvocationHandler:调用处理程序
动态代理的好处:
角色分析:
抽象角色:Rent.java
package pers.mobian.proxy.demo3;
public interface Rent {
public void rent();
}
真实角色:Host.java
package pers.mobian.proxy.demo3;
public class Host implements Rent {
@Override
public void rent() {
System.out.println("我是房东,我有房子出租");
}
}
动态代理角色:ProxyInvocationHander.java
package pers.mobian.proxy.demo3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHander implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//通过接口得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
}
//对代理实例添加附属操作,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
Object result = method.invoke(rent, args);
signContract();
return result;
}
private void seeHouse(){
System.out.println("中介带你看房子");
}
private void signContract(){
System.out.println("中介帮忙签合同");
}
}
客户:User.java
package pers.mobian.proxy.demo3;
public class User {
public static void main(String[] args) {
Rent rent = new Host();
ProxyInvocationHander pih = new ProxyInvocationHander();
pih.setRent(rent);
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
}
测试结果
中介带你看房子
我是房东,我有房子出租
中介帮忙签合同
角色分析:
抽象角色:UserService.java
package pers.mobian.proxy.demo2;
public interface UserService {
public void add();
public void delte();
public void update();
public void selet();
}
真实角色:UserServiceImpl.java
package pers.mobian.proxy.demo2;
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("使用了增加方法");
}
@Override
public void delte() {
System.out.println("使用了删除方法");
}
@Override
public void update() {
System.out.println("使用了修改方法");
}
@Override
public void selet() {
System.out.println("使用了查找方法");
}
}
代理角色:Proxy.java
package pers.mobian.proxy.demo4;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHander 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);
}
//对代理实例添加附属操作,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(userService, args);
//通过反射获得具体的方法名
log(method.getName());
return result;
}
public void log(String method) {
System.out.println(method+"方法使用成功");
}
}
客户:User.java
package pers.mobian.proxy.demo4;
public class User {
public static void main(String[] args) {
UserService userServiceImpl = new UserServiceImpl();
ProxyInvocationHander pih = new ProxyInvocationHander();
pih.setUserService(userServiceImpl);
UserService userService = (UserService)pih.getProxy();
userService.add();
userService.delte();
userService.update();
userService.selet();
}
}
测试结果
使用了增加方法
add方法使用成功
使用了删除方法
delte方法使用成功
使用了修改方法
update方法使用成功
使用了查找方法
selet方法使用成功
总结:在静态代理的基础上,每次添加一个真实角色,就需要一个对应的代理类来执行相应的代理操作。当使用动态代理类以后,不再拥有实际的代理类,而是使用真实角色的功能,即抽象角色(也就是接口),最终使用户能够控制所有的继承了这个接口的真实类。解决了静态代理的缺点,避免了代码的臃肿。
将所有的接口变成Object类,继而达到复用的效果
package pers.mobian.proxy.demo4;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHander implements InvocationHandler {
//被代理的接口
private Object target;
public void setUserService(Object target) {
this.target = target;
}
//通过接口得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//对代理实例添加附属操作,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(target, args);
return result;
}
}