一、静态代理
要求:被代理类必须实现至少一个接口;代理类(程序员自己编写)也必须实现被代理类的接口,且实现其中的方法;代理类必须代理被代理类。
示例:
1、被代理类实现的接口:
public interface MoneyService {
public void sava(int money);
public void send(String src,String dest,int money);
}
2、被代理类:
public class MoneyServiceImpl implements MoneyService{
@Override
public void sava(int money) {
System.out.println("调用dao执行sql,存钱");
}
@Override
public void send(String src, String dest, int money) {
System.out.println("在转出人账户上减1000块钱");
System.out.println("在目标账户上加1000块钱");
}
}
代理类:
public class MoneyServiceProxy implements MoneyService{
private MoneyService target;//目标、代理、委托
public MoneyServiceProxy(MoneyService target) {
super();
this.target=target;
}
@Override
public void sava(int money) {
System.out.println("开启事务");
target.sava(money);
System.out.println("提交事务");
}
@Override
public void send(String src, String dest, int money) {
System.out.println("开启事务");
target.send(src, dest, money);
System.out.println("提交事务");
}
}
测试类:
public class StaticDelegate {
public static void main(String[] args) {
//创建代理类对象并且指定一个被代理类对象
MoneyService moneyService = new MoneyServiceProxy(new MoneyServiceImpl());
//调用service方法
moneyService.sava(1000);
moneyService.send("", "", 1000);
}
}
二、动态代理
1、JDK代理:使用Proxy类,可以自动生成代理类及代理类对象
要求:被代理类必须实现至少一个接口。
被代理类接口:
public interface MoneyService {
public void sava(int money);
public void send(String src,String dest,int money);
}
被代理类:
public class MoneyServiceImpl implements MoneyService{
@Override
public void sava(int money) {
System.out.println("调用dao执行sql,存钱");
}
@Override
public void send(String src, String dest, int money) {
System.out.println("在转出人账户上减1000块钱");
System.out.println("在目标账户上加1000块钱");
}
}
代理类工厂:
/*
* 代理类工厂:自动生成代理类以及代理类对象
* 1、拥有一个被代理类的对象
* 2、提供一个方法来获取代理类对象
*/
public class ProxyFactory {
private Object target;//被代理类对象
public ProxyFactory(Object target) {
super();
this.target=target;
}
//获取代代理类对象
public Object getProxyInstance() {
/*
* Proxy.newProxyInstance()
* 参数一:类加载器
* 参数二:被代理类实现的所有接口
* 参数三:方法处理器/方法拦截器
*
* 这个方法会自动生成一个类,而且该类驶向了target.getClass().getInterfaces()接口
*/
return Proxy.newProxyInstance(ProxyFactory.class.getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {//用于拦截代理类的方法,拦截后执行下面的invoke方法
/*
* invoke()
* 参数一:代理类对象
* 参数二:被调用的方法
* 参数三:调用方法时传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务");
//被代理类对象调用方法(执行SQL)
Object result = method.invoke(target, args);//执行被代理类方法
System.out.println("提交事务");
return result;
}
});
}
}
测试类:
public class Base {
public static void main(String[] args) {
ProxyFactory factory = new ProxyFactory(new MoneyServiceImpl());
Object obj = factory.getProxyInstance();
//
System.out.println(obj.getClass());
System.out.println(obj instanceof MoneyService);
if(obj instanceof MoneyService) {
MoneyService moneyService = (MoneyService) obj;
//调方法
moneyService.sava(1000);//调用代理类对象的方法,该方法将被代理类工厂中的方法处理器(方法拦截器)处理(拦截),之后将会执行处理器中的invoke方法,实现代理。
}
}
}
2、CGLIB代理:又称为子类代理,就是为被代理类自动生成一个子类
要求:需要第三方jar包;代理类需要实现jar包中的MethodInterceptor接口。
需要的第三方包:asm-3.3.1.jar;cglib-2.2.2.jar
被代理类:
public class UserService {
public void add() {
System.out.println("调用sql语句添加用户");
}
}
代理类工厂:
/*
* cglib动态代理工厂:创建代理类对象
* 1、实现方法拦截器接口(MethodInterceptor)
* 2、拥有一个被代理类对象
*/
public class CglibProxyFactory implements MethodInterceptor{
private Object target;
public CglibProxyFactory(Object target) {
super();
this.target=target;
}
/*
*obj 代表Cglib 生成的动态代理类 对象本身
*method 代理类中被拦截的接口方法 Method 实例
*args 接口方法参数
*proxy 用于调用父类真正的业务类方法。可以直接调用被代理类接口方法
*/
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("cglib开启事务");
Object result = method.invoke(target, args);
System.out.println("cglib提交事务");
return result;
}
//返回代理类对象
public Object getProxyInstance() {
//1、创建生成代理类的工具类
Enhancer enhancer = new Enhancer();
//2、指定代理类的父类是哪个类
enhancer.setSuperclass(target.getClass());
//3、设置回调函数
enhancer.setCallback(this);
//4、生成代理类对象
return enhancer.create();
}
}
测试类:
public class TestCglib {
public static void main(String[] args) {
CglibProxyFactory factory = new CglibProxyFactory(new UserService());
//获取代理类对象
Object obj = factory.getProxyInstance();
System.out.println(obj.getClass());
if(obj instanceof UserService) {
System.out.println("yes");
UserService userService = (UserService) obj;
userService.add();
}
}
}
静态代理:由程序员编辑代理类代码,实现代理模式;在编译期就生成了代理类。
基于 JDK 实现动态代理:
通过jdk提供的工具方法Proxy.newProxyInstance动态构建全新的代理类(继承Proxy类,并持有InvocationHandler接口引用 )字节码文件并实例化对象返回。(jdk动态代理是由java内部的反射机制来实例化代理对象,并代理的调用委托类方法)
被代理类和代理类的关系:兄弟、同胞关系
缺点:被代理类至少需要实现一个接口。
基于CGlib 动态代理模式:
基于继承被代理类生成代理子类,不用实现接口。只需要被代理类是非final 类即可。(cglib动态代理底层是借助asm字节码技术
代理类和被代理类的关系:继承关系(代理类继承被代理类)