前言

AOP 全名為:Aspect-Oriented Programming,在Java中如何實現呢?

  1. 透過Design Pattern 中的Proxy Pattern來實現
  2. 透過AspectJ or Spring Aop來實現

本章節主要講Proxy Pattern的實現方式

主要內容

  • 我們有個需求是,需要提升查詢的效能,所以我們的做法是增加Cache

Version 1

  • 第一個版本,我們先建立的代碼
  • 建立一個service 和一個repo,從repo 拿取相對應的user
public class FindUserService {

    private final UserRepo userRepo;

    public FindUserService(final UserRepo userRepo) {
        this.userRepo = userRepo;
    }

    public User find(String username) {
        return userRepo.findByUsername(username);
    }

}
@AllArgsConstructor
@NoArgsConstructor
@Data
@Builder
public class User {

    String username;

    String password;

}

public interface UserRepo {

    User findByUsername(String username);

}
public class UserAdapter implements UserRepo {

    private final Map<String, User> userMap;

    private final ReentrantReadWriteLock lock;

    public UserAdapter(final Map<String, User> userMap) {
        this.userMap = userMap;
        this.lock = new ReentrantReadWriteLock();
    }

    @Override
    public User findByUsername(final String username) {
        try {
            lock.readLock().lock();
            return userMap.get(username);
        } catch (Exception e) {
            //tbd error
            throw new RuntimeException(e);
        } finally {
            lock.readLock().unlock();
        }
    }
}

Version 2

  • 接者我們對UserAdapter進行refactor成proxy pattern

  • 建立UserProxyAdapter,且將Lock行為的程式都抽到這裡

public class UserProxyAdapter implements UserRepo {

    private final UserRepo userRepo;

    private final ReentrantReadWriteLock lock;

    //注入UserAdapter
    public UserProxyAdapter(UserRepo userRepo) {
        this.lock = new ReentrantReadWriteLock();
        this.userRepo = userRepo;
    }

    @Override
    public User findByUsername(final String username) {
        try {
            lock.readLock().lock();
            return userRepo.findByUsername(username);
        } catch (Exception e) {
            //tbd error
            throw new RuntimeException(e);
        } finally {
            lock.readLock().unlock();
        }
    }
}
  • 而原始的UserRepo,改為
public class UserAdapter implements UserRepo {

    private final Map<String, User> userMap;

    public UserAdapter(final Map<String, User> userMap) {
        this.userMap = userMap;
    }

    @Override
    public User findByUsername(final String username) {
        return userMap.get(username);
    }
}

小結

  • 這種方式的改動,讓我們的將關注點分離並且讓Code更好測試與達到SRP的目標

參考連結