java 동적 에이전트 설명 및 동적 에이전트와 주석으로 로그 기록 기능 구현

3714 단어 javaWeb
동적 에이전트의 개념
동적 에이전트는 프로그램이 실행하는 과정에서 자동으로 에이전트 대상을 만들어서 에이전트를 받는 대상을 대체하여 해당하는 작업을 수행하는 것이다. 예를 들어 우리가 이미 실행에 들어간 프로젝트 중 한 사용자가 User 대상에 대해 데이터베이스에 대한 삭제 수정 작업을 하는 데 사용했는데 어느 날 사용자에 대한 삭제 수정 작업을 할 때 해당하는 로그를 기록하도록 요구했다. 어떻게 해야 하지?설마 우리가 Userdao의 원본 코드를 직접 수정한 다음에 Userdao의 모든 방법에 로그 기록 기능을 추가하는 것은 불합리한 것이다. 이것은 자바의 OCP 원칙, 즉 수정에 대한 닫기와 확장에 대한 개방을 위배하는 것이다.예를 들어 기존 코드를 다음과 같이 변경합니다.
인터페이스 클래스
public interface IUserDao {
	public void add(User user);

	public User load(int id);

	public void delete(int id);
	
	public void update(User user);

}

실현 클래스
public class UserDao implements IUserDao {

	public void add(User user) {

		System.out.println("user added:" + user);
	}

	public User load(int id) {
		System.out.println("load user, id=" + id);
		return null;
	}

	public void delete(int id) {

		System.out.println("deleted user, id=" + id);
	}

	@Override
	public void update(User user) {
		System.out.println("updated user:" + user);
	}

}

비즈니스 클래스 인터페이스
public interface IUserService {
	public void add(User user);

	public void delete(int id);

	public User load(int id);
	
	public void update(User user);
}

비즈니스 클래스 구현 클래스
public class UserService implements IUserService {

	IUserDao userDao;

	public IUserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(IUserDao userDao) {
		this.userDao = userDao;
	}

	public void add(User user) {

		userDao.add(user);
	}

	public void delete(int id) {

		userDao.delete(id);
	}

	public User load(int id) {
		return userDao.load(id);
	}

	@Override
	public void update(User user) {
		userDao.update(user);
	}

}

현재 UserDao의 모든 메서드 실행 전 로그를 기록한 다음 로그를 출력하기 위한 Logger 클래스를 정의했습니다.
public class Logger {
	public static void log(String info) {
		System.out.println(info);
	}

}

또한 다음과 같은 프록시 클래스를 구현했습니다.
// 1、 InvocationHandler
public class LogProxy implements InvocationHandler {
	// 2、 
	private Object target;
	// 3、 , , 
	public static Object getInstance(Object o) {
		LogProxy proxy = new LogProxy();
		proxy.target = o;
		Object result = Proxy.newProxyInstance(o.getClass().getClassLoader(),
				o.getClass().getInterfaces(), proxy);
		return result;
	}

	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		if (method.isAnnotationPresent(LogInfo.class)) { //  LogInf 
			LogInfo li = method.getAnnotation(LogInfo.class); //  
			Logger.log(new Date().toString() + " ---> " + li.value()); //  , 
		}
		Object o = method.invoke(target, args);
		return o;
	}

}
사용자 정의 Annotation은 다음과 같습니다.
@Retention(RetentionPolicy.RUNTIME)
public @interface LogInfo {

	public String value() default ""; 
}

모든 것이 끝난 후에 만약에 우리가 대응하는 방법을 실행하기 전에 로그를 기록하고 싶다면 IUserDao의 로그를 추가하고 싶은 방법에서 LogInfo 주석을 사용하면 방법이 실행될 때 자동으로 로그 기록 기능을 추가할 수 있다. 다음과 같다.
public interface IUserDao {
	@LogInfo("Add a user")
	public void add(User user);

	public User load(int id);

	@LogInfo("Delete a user")
	public void delete(int id);
	
	@LogInfo("Update a user")
	public void update(User user);

}

@LogInfo 주석이 붙어야만 로그를 기록할 수 있습니다. 예를 들어dd, delete, update,load는 로그를 기록하지 않기 때문에 주석을 이용하여 어떤 방법으로 로그를 기록하고 싶은지 유연하게 제어할 수 있습니다.
사용
public static void main(String[] args) {
		IUserDao userDao = new UserDao();
		IUserDao userDaoProxy = (IUserDao) LogProxy.getInstance(userDao);
		
		UserService userService = new UserService();
		userService.setUserDao(userDaoProxy);
		userService.add(new User());
	}

좋은 웹페이지 즐겨찾기