静态代理及动态代理原理及简单实现

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_34033209/article/details/77829203
一、什么是代理
代理其实就是一种模式,其目的就是为了解决在直接访问对象时带来的问题
二、代理模式
代理模式是常用的java设计模式,特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等
代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。 
按照代理的创建时期,代理类可以分为两种: 
静态代理:由程序员创建或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。 
动态代理:在程序运行时运用反射机制动态创建而成。
三、单个静态代理


public interface CountDao { 
// 查看账户方法 
public void queryCount(); 



public class CountDaoImpl implements CountDao { 
public void queryCount() { 
System.out.println("查看账户方法..."); 




public class CountTrancProxy implements CountDao { 
private CountDao countDao; 
public CountProxy(CountDao countDao) { 
this.countDao = countDao; 



@Override 
public void queryCount() { 
System.out.println("tranc start"); 
countDao.queryCount(); 
System.out.println("tranc end"); 




public class TestCount { 
public static void main(String[] args) { 
CountTrancProxy countProxy = new CountTrancProxy(new CountDaoImpl()); 
countProxy.updateCount(); 


四、多个静态代理


public class CountLogProxy implements CountDao { 
private CountDao countDao; 
public CountLogProxy(CountDao countDao) { 
this.countDao = countDao; 



@Override 
public void queryCount() { 
System.out.println("Log start"); 
countDao.queryCount(); 
System.out.println("Log end"); 




调用:
// 体现了聚合的思想,代理之间的组合 
public static void main(String[] args) { 
CountTrancProxy trancProxy = new CountTrancProxy(new CountDaoImpl()); 
CountLogProxy logPro = new CountLogProxy(trancProxy); 
logPro.queryCount(); 



输出:
Log start 
事务处理之前 
查看账户方法... 
事务处理之后 
Log end 
五、静态代理的问题
(1)、代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样做会造成大量的代码冗余。若一个接口增加了一个方法,代理类和接口实现类都必须实现该方法。增加了代码的维护难度、
(2)代理对象只服务于一种特定类型的对象,假如要服务于多种类型的对象,代理类就显得捉襟见肘、力不从心了

六、动态代理

IUserService接口:
package com.hap.proxy;

public interface IUserService {
void addFriend();


void addGroup();


void publishLog();


void publishComments();


void publishWords();


void deleteWords();
}



Permission注解:
package com.hap.proxy;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface Permission {
public String value();
}


接口实现类:
package com.hap.proxy;
//被代理对象
public class UserService implements IUserService{


@Override
@Permission("添加好友")
public void addFriend() {
System.out.println("添加了好友");
}


@Override
@Permission("添加群组")
public void addGroup() {
System.out.println("添加了群组");
}


@Override
@Permission("发布日志")
public void publishLog() {
System.out.println(" 发布了日志");
}


@Override
@Permission("发布评论")
public void publishComments() {
System.out.println("发布了评论");
}


@Override
@Permission("发布留言")
public void publishWords() {
System.out.println("发布了留言");
}


@Override
public void deleteWords() {
System.out.println("删除了留言");
}
}


用户实体类:
package com.hap.proxy;
import java.util.ArrayList;

public class User{
private String username;
private String password;


/**
* 保存用户权限集合
*/
private ArrayList<String> list = new ArrayList<String>();


public User() {
super();
// TODO Auto-generated constructor stub
}


public User(String username, String password) {
super();
this.username = username;
this.password = password;
}


public String getUsername() {
return username;
}


public void setUsername(String username) {
this.username = username;
}


public String getPassword() {
return password;
}


public void setPassword(String password) {
this.password = password;
}


public ArrayList<String> getList() {
return list;
}


public void setList(ArrayList<String> list) {
this.list = list;
}


@Override
public String toString() {
return "User [username=" + username + ", password=" + password + "]";
}
}




UserDao模拟数据库(为客户端提供假数据)
package com.hap.proxy;

import java.util.ArrayList;

public class UserDao {


private static ArrayList<User> userList = new ArrayList<User>();
static {
User u1 = new User("itcast", "itcast");
u1.getList().add("添加好友");
u1.getList().add("删除评论");
userList.add(u1);


User u2 = new User("itheima", "itheima");
u2.getList().add("添加好友");
u2.getList().add("删除评论");
u2.getList().add("添加群组");
userList.add(u2);
}


public static User getUser(String username, String password) {
for (User user : userList) {
if (username.equals(user.getUsername()) && password.equals(user.getPassword())) {
return user;
}
}
return null;
}
}




代理对象工厂
package com.hap.proxy;

import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ServiceFactory {


public static IUserService getService(User user) {
UserService userService = new UserService();
ClassLoader loader = userService.getClass().getClassLoader();
Class<?>[] interfaces = userService.getClass().getInterfaces();
MyInvocationHandler h = new MyInvocationHandler(userService, user);


// 通过Proxy创建代理对象
IUserService service = (IUserService) Proxy.newProxyInstance(loader, interfaces, h);
return service;
}
}


class MyInvocationHandler implements InvocationHandler {


private UserService userService;
private User user;


public MyInvocationHandler(UserService userService, User user) {
this.userService = userService;
this.user = user;
}


@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// 拿到方法名字
String name = method.getName();
// 拿到方法的参数
Class<?>[] parameterTypes = method.getParameterTypes();
// 通过反射获取UserInterfaceImpl里面的方法
Method m = userService.getClass().getMethod(name, parameterTypes);
// 获取方法上面的 注解
Permission userAnnotation = m.getAnnotation(Permission.class);
// 获取注解里面的参数内容,然后与用户的权限进行比较
if (null == userAnnotation) {
System.out.println("执行该方法不需要权限");
return method.invoke(userService, args);
}


// 如果注解内容不为空,说明需要权限才能有这个操作
if (user.getList().contains(userAnnotation.value())) {
System.out.println("该操作需要权限,但是" + user.getUsername() + " 具有该权限");
return method.invoke(userService, args);
} else {
System.out.println("该操作需要权限,但是" + user.getUsername() + " 不具有该权限");
}


return null;
}
}


客户端:
package com.hap.proxy;

import java.util.Scanner;

public class UserClient {
public static void main(String[] args) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("请输入涌户名:");
String username = br.readLine();
System.out.println("请输入密码:");
String password = br.readLine();


// 校验(不管校验是否成功都要返回结果)
User user = UserDao.getUser(username, password);
if (null == user) {
System.out.println("用户不存在");
return;
}


System.out.println("欢迎登陆");
while (true) {
System.out.println("请选择操作:1.添加好友 2.添加群组 3.发布日志 4.发布评论 5.发不留言 6.删除留言 7.退出");


// 获取一个代理对象
IUserService userInterface = UserSeriveFactory.getService(user);
String choice = br.readLine();


switch (choice) {
case "1":
userInterface.addFriend();
break;
case "2":
userInterface.addGroup();
break;
case "3":
userInterface.publishLog();
break;
case "4":
userInterface.publishComments();
break;
case "5":
userInterface.publishWords();
break;
case "6":
userInterface.deleteWords();
break;
case "7":
default:
System.out.println("谢谢使用");
return;
}
}
}


猜你喜欢

转载自blog.csdn.net/qq_34033209/article/details/77829203