静态代理
流程图:
代理类:
package com.gao.demo02;
public class UserServiceProxy 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.add();
}
public void update(){
log("update");
userService.add();
}
public void query(){
log("query");
userService.add();
}
public void log(String msg){
System.out.println("[Debug]使用了"+msg+"方法");
}
}
被代理类:
package com.gao.demo02;
public class UserServiceImpl implements UserService{
public void add(){
System.out.println("增加了一个用户");
}
public void delete(){
System.out.println("删除了一个用户");
}
public void update(){
System.out.println("修改了一个用户");
}
public void query(){
System.out.println("查询了一个用户");
}
}
main:
package com.gao.demo02;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
}
}
接口:
package com.gao.demo02;
public interface UserService {
void add();
void delete();
void update();
void query();
}
分析:
静态代理类优缺点
优点:业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
缺点:
1)代理对象的一个接口只服务于一种类型的对象,如果要代理的方法很多,势必要为每一种方法都进行代理,静态代理在程序规模稍大时就无法胜任了。
2)如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
动态代理
流程图:
代理类:
package com.gao.demo04;
import com.gao.demo03.Rent;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//这个可以做成一个公共类
//这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setTarget(Object target) {
this.target = target;
}
//生成代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable{
log(method.getName());
//动态代理的本质就是使用反射机制实现(通过invoke方法,反射执行代理类)
Object result =method.invoke(target,args);
return result;
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}
}
被代理类:
package com.gao.demo03;
public class Host implements Rent {
public void rent(){
System.out.println("房东要出租房子!");
}
}
接口:
package com.gao.demo03;
public interface Rent {
public void rent();
}
main:
package com.gao.demo04;
import com.gao.demo02.UserService;//使用了demo2的类
import com.gao.demo02.UserServiceImpl;
public class Client {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
//代理角色,不存在
ProxyInvocationHandler pih = new ProxyInvocationHandler();
pih.setTarget(userService);//设置要代理的对象
//动态生成代理类
UserService proxy = (UserService) pih.getProxy();
proxy.delete();
}
}
分析:
我们可以通过LogHandler代理不同类型的对象,如果我们把对外的接口都通过动态代理来实现,那么所有的函数调用最终都会经过invoke函数的转发,因此我们就可以在这里做一些自己想做的操作,比如日志系统、事务、拦截器、权限控制等。这也就是AOP(面向切面编程)的基本原理。