JDK 와 Cglib 는 동적 에이전트 인 스 턴 스 및 장단 점 분석 을 실현 합 니 다.

6912 단어
Spring AOP 가 사용 하 는 핵심 기술 은 동적 에이전트 입 니 다. 동적 대 리 는 디자인 모델 중의 에이전트 모델 과 연결 되 어야 합 니 다. 대리 모델 을 통 해 우 리 는 목표 류 에 대해 기능 을 강화 할 수 있 습 니 다. 특정한 방법의 집행 전후 에 조작 을 추가 할 수 있 습 니 다. 예 를 들 어 계산 방법 집행 효율, 인쇄 로그 등 입 니 다.
아래 의 예 를 들 어 우 리 는 목표 클래스 Target 이 있 습 니 다. 우 리 는 목표 클래스 의 test 방법 에 로그 인쇄 기능 을 추가 해 야 합 니 다. 이때 우 리 는 프 록 시 모드 를 통 해 실현 할 수 있 습 니 다.
package com.proxy.test;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

class Target {
	public void test(){
		System.out.println("Target test");
	}
}

class TargetProxy
{
	private Target target;
	private Log logger = LogFactory.getLog(TargetProxy.class);
	public TargetProxy(Target target) {
		this.target = target;
	}
	public void test()
	{
		logger.info("*****     **********");
		target.test();
		logger.info("*****     **********");
	}
}

public class ProxyTest{
	public static void main(String[] args) {
		Target target = new Target();
		TargetProxy proxy = new TargetProxy(target);
		proxy.test();
		
	}
}
위의 예 에서 우 리 는 프 록 시 클래스 TargetProxy 를 통 해 목표 클래스 에 대한 기능 을 강화 합 니 다. 동적 프 록 시 란 프로그램 이 실행 되 는 동안 메모리 에서 프 록 시 클래스 의 바이트 코드 를 동적 으로 생 성하 고 프 록 시 대상 을 예화 하 는 것 을 말 합 니 다.
실현 방식 은 두 가지 가 있 는데 하 나 는 JDK 자체 의 동적 대 리 를 통 해 이 루어 지 는 것 이 고 다른 하 나 는 Cglib 를 사용 하여 이 루어 지 는 것 이다.
1. JDk 를 사용 하여 동적 에이전트 구현
예 를 들 어 Service 층 에서 저 희 는 두 가지 업무 논리 류 인 Login ServiceImpl 과 User ServiceImpl 이 있 습 니 다.
interface LoginService{
	public boolean checkUser();
}

class LoginServiceImpl implements LoginService{
	@Override
	public boolean checkUser() {
		System.out.println("LoginServiceImpl  checkUser");
		return false;
	}
}

interface UserService{
	public String getUserName();
}

class UserServiceImpl implements UserService{

	@Override
	public String getUserName() {
		System.out.println("UserServiceImpl getUserName");
		return null;
	}
	
}
저 희 는 LoginServiceImpl 과 UserServiceImpl 의 방법 에 로그 인쇄 기능 을 추가 하려 고 합 니 다. Jdk 동적 대 리 를 통 해 이 루어 질 수 있 습 니 다. 사례 코드 는 다음 과 같 습 니 다.
package com.proxy.test.jdk;

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

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


interface LoginService{
	public boolean checkUser();
}

class LoginServiceImpl implements LoginService{
	@Override
	public boolean checkUser() {
		System.out.println("LoginServiceImpl  checkUser");
		return false;
	}
}

interface UserService{
	public String getUserName();
}

class UserServiceImpl implements UserService{

	@Override
	public String getUserName() {
		System.out.println("UserServiceImpl getUserName");
		return null;
	}
	
}

class ProxyHandler implements InvocationHandler{
	private Object target;
	private Log logger = LogFactory.getLog(ProxyHandler.class);
	
	public void setTarget(Object target) {
		this.target = target;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] param)
			throws Throwable {
		logger.info("*********       ************");
		Object retObj = method.invoke(target, param);
		logger.info("*********       ************");
		return retObj;
	}
	
}


public class ProxyTestJDK {
	public static void main(String[] args) {
		//      
		LoginService loninService = new LoginServiceImpl();
		UserService userService = new UserServiceImpl();
		
		
		
		ProxyHandler proxyHandler = new ProxyHandler();
		//  LoginService    
		proxyHandler.setTarget(loninService);
		LoginService loninService$Proxy = (LoginService) Proxy.newProxyInstance(loninService.getClass().getClassLoader(),
				loninService.getClass().getInterfaces(), proxyHandler);
		loninService$Proxy.checkUser();
		
		//  UserService    
		proxyHandler.setTarget(userService);
		UserService userService$Proxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(),
				userService.getClass().getInterfaces(), proxyHandler);
		userService$Proxy.getUserName();
	}
}
실행 프로그램 출력:
   17, 2015 1:37:21    com.proxy.test.cglib.CglibProxy intercept
  : *********       ************
LoginServiceImpl  checkUser
   17, 2015 1:37:21    com.proxy.test.cglib.CglibProxy intercept
  : *********       ************
   17, 2015 1:37:21    com.proxy.test.cglib.CglibProxy intercept
  : *********       ************
UserServiceImpl getUserName
   17, 2015 1:37:21    com.proxy.test.cglib.CglibProxy intercept
  : *********       ************

2. Cglib 동적 에이전트 사용
위의 수요 에 대해 우 리 는 Cglib 를 통 해 실현 할 수 있 습 니 다. 구체 적 인 코드 는 다음 과 같 습 니 다.
package com.proxy.test.cglib;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
interface LoginService{
	public boolean checkUser();
}

class LoginServiceImpl implements LoginService{
	@Override
	public boolean checkUser() {
		System.out.println("LoginServiceImpl  checkUser");
		return false;
	}
}

interface UserService{
	public String getUserName();
}

class UserServiceImpl implements UserService{

	@Override
	public String getUserName() {
		System.out.println("UserServiceImpl getUserName");
		return null;
	}
	
}

class CglibProxy implements MethodInterceptor
{
	private Log logger = LogFactory.getLog(CglibProxy.class);


	@Override
	public Object intercept(Object proxy, Method method, Object[] params,
			MethodProxy methodProxy) throws Throwable {
		logger.info("*********       ************");
		Object retObj = methodProxy.invokeSuper(proxy, params);
		logger.info("*********       ************");
		return retObj;
	}
	//           
	public Object newProxy(Object target)
	{
		Enhancer enhancer = new Enhancer();
		enhancer.setSuperclass(target.getClass());
		enhancer.setCallback(this);
		enhancer.setClassLoader(target.getClass().getClassLoader());
		return enhancer.create();
	}
}
public class ProxyTestCglib {

	public static void main(String[] args) {
		//      
		LoginService loninService = new LoginServiceImpl();
		UserService userService = new UserServiceImpl();
		CglibProxy proxy = new CglibProxy();
		//      
		LoginService loninService$Proxy = (LoginService)proxy.newProxy(loninService);
		UserService userService$Proxy = (UserService)proxy.newProxy(userService);
		loninService$Proxy.checkUser();
		userService$Proxy.getUserName();
		
	}
}

3. 양자 장단 점 분석
JDK 동적 에이 전 트 를 사용 하면 대상 클래스 가 구현 해 야 하 는 특정한 인 터 페 이 스 를 사용 합 니 다. 만약 에 특정한 클래스 가 인 터 페 이 스 를 실현 하지 않 으 면 에이전트 대상 을 생 성 할 수 없습니다.
cglib 원 리 는 목표 클래스 에 대해 하나의 하위 클래스 를 생 성하 고 그 중의 모든 방법 을 덮어 쓰 는 것 이기 때문에 목표 클래스 와 방법 은 final 유형 으로 설명 할 수 없습니다.
실행 효율 적 으로 볼 때 Cglib 동적 대리 효율 이 비교적 높다.
다음으로 전송:https://www.cnblogs.com/lanzhi/p/6468573.html

좋은 웹페이지 즐겨찾기