Java框架(五)之代理模式

一、静态代理

1.定义

为其他对象提供一种代理来控制这个对象的访问

2.优点

  • 职责清晰

  • 保护目标对象

  • 高扩展性

3.结构

  • 目标类
  • 代理对象
  • 目标类和代理类实现同一个接口

4.案例(中介帮房东租房子)

(1)ZuFangZi接口
public interface ZuFangZi {
	public void lookHouse();
	public void getmoney(double money);
}
(2)FangDong类(被代理类)
public class FangDong implements ZuFangZi {
	@Override
	public void lookHouse() {
		// TODO Auto-generated method stub
		System.out.println("看房东房子");
	}
	@Override
	public void getmoney(double money) {
		// TODO Auto-generated method stub
		System.out.println("房东收房租"+money+"元");
	}
}
(3)ZhongJie 类(代理类)
public class ZhongJie implements ZuFangZi {
	//传入被代理对象
	private  FangDong fangDong;
	public ZhongJie(FangDong fangDong) {
		// TODO Auto-generated constructor stub
		this.fangDong=fangDong;
	}
	
	@Override
	public void lookHouse() {
		// TODO Auto-generated method stub
		System.out.println("中介带客户看房子");
		fangDong.lookHouse();
		System.out.println("中介带客户看房子完毕");
	}
	@Override
	public void getmoney(double money) {
		// TODO Auto-generated method stub
		double ZhongJieMoney=3000.0;
		System.out.println("中介收取中介费"+ZhongJieMoney);
		fangDong.getmoney(money-ZhongJieMoney);
	}
}
(4)测试类people
ZhongJie zhongJie=new ZhongJie(new FangDong());
		zhongJie.lookHouse();
		zhongJie.getmoney(10000);

二、动态代理(重难点)

1.定义

直接给某一个目标对象生成一个代理对象,不需要代理类

2.分类

  • JDK动态代理 要求:接口 + 实现类 spring底层默认使用该方式创建代理对象
  • cglib方式 要求:实现类 (给目标类创建一个子类) spring 可以使用cglib字节码增强 实现aop

3.JDK动态代理(必须有接口)

(1)结构
  • 目标类:接口 + 实现类 (被代理的类 需要增强的)
  • 通知类:用于存通知 MyAdvice
  • 工厂类:编写工厂生成代理
  • 测试
(2)案例(图书)
a.BookService 接口(被代理类)
public interface BookService {
	public void add();
	public void delete();
	public void update();
}
b.BookServiceImpl 类(被代理类实现类)
public class BookServiceImpl implements BookService{
	@Override
	public void add() {
		System.out.println("add");
		int i=10/0;//模拟断电
	}
	@Override
	public void delete() {
		System.out.println("delete");
	}
	@Override
	public void update() {
		System.out.println("update");
	}
}
c.MyAdvice (增强类)
public class MyAdvice {
	public   void before() {
		System.out.println("前置通知---开启事务");
	}
	public void after() {
		System.out.println("后置通知-----提交事务");
	}
}
d.MyProxyFactory (工厂类)
public class MyProxyFactory {
public  static  BookService  createProxyInstance() {
		//1,创建被代理对象(目标类)
		BookServiceImpl bookServiceImpl = new BookServiceImpl();
		//2,通过jdk中提供的Proxy类 能够创建一个代理对象
		/**
		 * loader, 类加载器
		 * interfaces,被代理对象实现的接口列表
		 *  h 调用方法处理器
		 */
		MyAdvice advice  = new MyAdvice();
	return 	(BookService) Proxy.newProxyInstance(bookServiceImpl.getClass().getClassLoader()
			,bookServiceImpl.getClass().getInterfaces() ,
				new InvocationHandler() {
					
					/**
					 * 参数一:代理对象  一般没用
					 * 参数二:调用的目标类的方法所代表的method对象
					 * 参数三:传递给目标类的方法的参数列表
					 */
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
						//System.out.println("开启事务");//前置通知/增强
						long start = System.currentTimeMillis();
						advice.before();
						//调用目标类的方法
						Object o = null;
						try {
							 o = method.invoke(bookServiceImpl, args);
							//System.out.println("提交事务");//后置通知/增强 advice
							 advice.after();
							long end = System.currentTimeMillis();
							System.out.println(end-start);
						}catch (Exception e) {
							System.out.println("回滚事务");
						}
						return o;
					}
				});
	}
}
e.测试类
//得到代理对象
		BookService bookService =  MyProxyFactory.createProxyInstance();
			bookService.add();
			 bookService.update(); 
			 bookService.delete();
			 bookService.deleteByName();
			 bookService.updateType();
			 bookService.updateByName();

4.cglib方式

(1)介绍
  • 没有接口,只有实现类。
  • 采用字节码增强框架 cglib,在运行时 创建目标类的子类,从而对目标类进行增强。
(2)案例(图书)
a.BookServiceImpl(被代理对象实现类)
public class BookServiceImpl  {
	
	public  void add() {
		//开启事务
	
		System.out.println("add");
		int  i = 10/0;//模拟断电
		//提交事务
		
		//回滚事务
		//}
		
	}
	
	public  void delete() {
		//开启事务
		try {
		System.out.println("delete");
		//提交事务
		}catch (Exception e) {
			//回滚事务
		}
		
	}
	
	public  void update() {
		//开启事务
		try {
		System.out.println("update");
		//提交事务
		}catch (Exception e) {
			//回滚事务
		}
		
	}


	public  void updateType() {
		//开启事务
		try {
		System.out.println("updateType");
		//提交事务
		}catch (Exception e) {
			//回滚事务
		}
		
	}

	public  void deleteByName() {
		//开启事务
				try {
				System.out.println("deleteByName");
				//提交事务
				}catch (Exception e) {
					//回滚事务
				}
	}
	public  void updateByName() {
		//开启事务
		try {
		System.out.println("updateByName");
		//提交事务
		}catch (Exception e) {
			//回滚事务
		}
	}
}
b.MyAdvice (通知类)
public class MyAdvice {
	public   void before() {
		System.out.println("前置通知---开启事务");
	}
	public void after() {
		System.out.println("后置通知-----提交事务");
	}
	
	public void exceptionAdvice() {
		System.out.println("异常通知----回滚事务");
	}
}
c.MyCglibProxyFactory (工厂)
public class MyCglibProxyFactory {
	public static BookServiceImpl createProxy() {
		//1,创建目标类的对象
		BookServiceImpl bookServiceImpl = new BookServiceImpl();
		//2,创建cglib的核心对象
		Enhancer  enhancer = new  Enhancer();
		//3,创建增强类的对象
		MyAdvice  advice  = new MyAdvice();
		//4,设置enhancer父类
		enhancer.setSuperclass(bookServiceImpl.getClass());
		//5,设置回调函数  通过代理对象调用方法时会执行回调函数中的  intercept 方法
		enhancer.setCallback(new MethodInterceptor() {
			
			/**
			 * Object arg0,代理对象  一般用不到
			 * Method arg1, 调用的方法的method对象
			 * Object[] arg2, 参数列表
			 * MethodProxy arg3   代理方法本身  一般用不到
			 */
			@Override
			public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
				advice.before();
				//通过反射调用目标类的方法
				Object  o = null;
				try {
					o = method.invoke(bookServiceImpl, args);
					  advice.after();
				}catch (Exception e) {
					advice.exceptionAdvice();
				}
				return o;//目标类的返回值
			}
		});	
		//6.创建这个代理对象
		return (BookServiceImpl) enhancer.create();		
	}
}
d.测试类
BookServiceImpl bookServiceImpl = MyCglibProxyFactory.createProxy();
		bookServiceImpl.add();
		bookServiceImpl.delete();
		bookServiceImpl.update();
		bookServiceImpl.deleteByName();
		bookServiceImpl.updateByName();

5.总结

  • Jdk代理:必须有接口和目标类 动态的给接口创建一个实现类方式创建的代理类
  • Cglib:不需要接口 给目标类创建一个子类方式实现的代理方式
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值