八: 动态代理的几种实现方式及优缺点

  1. 动态代理

    八: 动态代理的几种实现方式及优缺点_第1张图片
    八: 动态代理的几种实现方式及优缺点_第2张图片

JDK 代码示例: 需求, user 实体类 值写入到数据库时, 校验name 长度不能小于1
无侵入性增强

  1. 有个接口 UserService
package com.enjoylearning.dynamic.proxy.jdk;

import com.enjoylearning.dynamic.proxy.User;

public interface UserService {
	
	void addUser(User user);

}
  1. 被增强的类必须要继承接口
package com.enjoylearning.dynamic.proxy.jdk;

import com.enjoylearning.dynamic.proxy.User;

public class UserServiceImpl implements UserService {

	@Override
	public final void addUser(User user) {
		System.out.println("用户数据入库成功,数据为:" + user.toString());
	}

}

3.拦截器

package com.enjoylearning.dynamic.proxy.jdk;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.util.logging.Logger;

import com.enjoylearning.dynamic.proxy.User;

public class UserServiceInterceptor implements InvocationHandler{

	private Object realObj;
	
	private static Logger logger = Logger.getLogger(UserServiceInterceptor.class.getName());
	
	public Object getRealObj() {
		return realObj;
	}

	public void setRealObj(Object realObj) {
		this.realObj = realObj;
	}


	public UserServiceInterceptor(Object realObj) {
		super();
		this.realObj = realObj;
	}


	public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
		if(args!=null && args.length>0 && args[0] instanceof User){
			User user = (User) args[0];
			if(user.getName().trim().length()<=1){
				throw new RuntimeException("用户姓名输入长度需要大于1!");
			}
		}
		Object ret = method.invoke(realObj, args);
		logger.info("数据库操作成功!");
		return ret;
	}
	
	

}

4.测试方法

package com.enjoylearning.dynamic.proxy.jdk;

import java.lang.reflect.Proxy;

import com.enjoylearning.dynamic.proxy.User;

public class Client {

	public static void main(String[] args) {
		User user = new User();
		user.setAddress("地址");
		user.setAge(20);
		user.setName("1ison");
		UserService us = new UserServiceImpl();
		UserServiceInterceptor usi = new UserServiceInterceptor(us);
		//1.类加载器
		//2. 服务接口信息
		//3. invocationhandler 本身
		UserService proxy = (UserService) Proxy.newProxyInstance(us.getClass().getClassLoader(), us.getClass().getInterfaces(), usi);
		//通过动态代理增强业务
		proxy.addUser(user);
//		System.out.println("---------------------");
//		System.out.println(proxy.hashCode());
	}
}

CGLIB 动态代理

八: 动态代理的几种实现方式及优缺点_第3张图片
1.被增强的 方法, 不需要继承接口

package com.enjoylearning.dynamic.proxy.cglib;

import com.enjoylearning.dynamic.proxy.User;

public class UserServiceImpl {
	


	public final void addUser(User user) {
		System.out.println("用户数据入库成功,数据为:"+user.toString());
	}

}

2.拦截器 实现intercept 方法

package com.enjoylearning.dynamic.proxy.cglib;

import java.lang.reflect.Method;
import java.util.logging.Logger;

import com.enjoylearning.dynamic.proxy.User;

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

public class UserServiceInterceptor implements MethodInterceptor {

	private static Logger logger = Logger.getLogger(UserServiceInterceptor.class.getName());

	public Object intercept(Object obj, Method method, Object[] args,MethodProxy proxy) throws Throwable {
		if(args!=null && args.length>0 && args[0] instanceof User){
			User user = (User) args[0];
			if(user.getName().trim().length() <= 1){
				throw new RuntimeException("用户姓名输入长度需要大于1!");
			}
		}
		Object ret = proxy.invokeSuper(obj, args);
		logger.info("数据库操作成功!");
		return ret;
	}

}

  1. 测试类
package com.enjoylearning.dynamic.proxy.cglib;

import com.enjoylearning.dynamic.proxy.User;

import net.sf.cglib.proxy.Enhancer;

public class Client {
	
	public static void main(String[] args) {
		User user = new User();
		user.setAddress("地址");
		user.setAge(20);
		user.setName("lison");
		Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(UserServiceImpl.class);
        enhancer.setCallback(new UserServiceInterceptor());
        UserServiceImpl usi1 = (UserServiceImpl) enhancer.create();
        usi1.addUser(user);
//		System.out.println("---------------------");
//		System.out.println(usi.hashCode());
        
//        UserServiceImpl us = new UserServiceImpl();
//        enhancer.setCallback(new UserServiceDelegateInterceptor(us));
//        UserServiceImpl usi2 = (UserServiceImpl) enhancer.create();
//        usi2.addUser(user);
	}

}

八: 动态代理的几种实现方式及优缺点_第4张图片

你可能感兴趣的:(面试题)