一、静态代理
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:不需要接口 给目标类创建一个子类方式实现的代理方式