spring 기술 내막 깊이 탐색 (6): JDK 동적 에이전트 와 cglib 생 성 에이전트

[JDK 생 성 에이전트]
JDK 에 서 는 프 록 시 클래스 를 동적 으로 생 성 할 수 있 는 프 록 시 클래스 를 제공 합 니 다.
권한 관리 시스템 을 만 들 려 면 사용자 가 특정한 방법 에 대한 접근 을 제어 해 야 합 니 다. user 가 null 이면 save 방법 에 접근 하지 못 하 게 합 니 다.
① 인터페이스 클래스: PersonService
public interface PersonService {
	public void save();
}

② 실현 류: PersonServiceImpl
public class PersonServiceImpl implements PersonService {
	private String user;
	
	public PersonServiceImpl(){
	}
	
	public PersonServiceImpl(String user) {
		this.user = user;
	}

	public void save() {
		System.out.println("   save()  ");
	}

	public String getUser() {
		return user;
	}
}

③ 대리 공장 생 성: JDKProxyFactory
public class JDKProxyFactory implements InvocationHandler {
	private Object targetObject; //       

	public Object createProxyIntance(Object targetObject) {
		this.targetObject = targetObject;
	    /**
		 *                 ,               
		 *                
		 *            ,            ,            invoke  
		 */
		return Proxy.newProxyInstance(this.targetObject.getClass().getClassLoader(), 
									  this.targetObject.getClass().getInterfaces(), 
									  this);
	}

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		PersonServiceImpl ps = (PersonServiceImpl) this.targetObject;
		Object result = null;
		if (ps.getUser() != null) { //   user null,          
			result = method.invoke(targetObject, args); //             
		}
		return result;
	}
}

④ 테스트 한 번:
public class PersonServiceImplTest {
	@Test
	public void testJDKProxy() {
		JDKProxyFactory factory = new JDKProxyFactory();
		PersonService personService = (PersonService) factory.createProxyIntance(new PersonServiceImpl("zhangsan"));
		personService.save();
	}
}

[CGLIB 생 성 에이전트]
Cglib 는 우수한 동적 프 록 시 프레임 워 크 입 니 다. 바 텀 은 ASM 을 사용 하여 메모리 에서 프 록 시 클래스 의 하위 클래스 를 동적 으로 생 성 합 니 다.
CGLIB 생 성 에이 전 트 를 사용 하려 면 cglib - node - 2.1 을 도입 해 야 합 니 다.3.jar
① CBLIG 생 성 대행 공장: CGlibProxyFactory
public class CGlibProxyFactory implements MethodInterceptor {
	private Object targetObject;

	public Object createProxyIntance(Object targetObject) {
		this.targetObject = targetObject;
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(this.targetObject.getClass()); //         
		enhancer.setCallback(this); //       
		return enhancer.create();
	}

	public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
		PersonServiceImpl bean = (PersonServiceImpl) this.targetObject;
		Object result = null;
		if (bean.getUser() != null) { //   user null,          
			result = methodProxy.invoke(targetObject, args);
		}
		return result;
	}
}

② 테스트 한 번
public class PersonServiceImplTest {
	@Test
	public void testCGLIBProxy() {
		CGlibProxyFactory factory = new CGlibProxyFactory();
		PersonService personService = (PersonServiceImpl) factory.createProxyIntance(new PersonServiceImpl("lisi"));
		personService.save();
	}
}

[두 대리 비교!]
1. JDK 의 동적 에이 전 트 를 사용 하면 피 에이 전 트 는 반드시 특정한 인 터 페 이 스 를 실현 해 야 한다. CGLIB 를 사용 하면 피 에이 전 트 는 어떠한 인터페이스 도 실현 하지 못 하고 동적 에이 전 트 를 실현 할 수 있다. 
2. 계승 을 사용 하기 때문에 cglib 는 final 수식 을 사용 하 는 클래스 에 대 리 를 사용 할 수 없습니다.
3. CGLIB 의 속 도 는 JDK Proxy 동적 에이전트 보다 훨씬 빠르다.

좋은 웹페이지 즐겨찾기