Java 代理模式
0.代理的概念:
代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。
1.静态代理:
优点:静态代理模式在不改变目标对象的前提下,实现了对目标对象的功能扩展。
不足:静态代理实现了目标对象的所有方法,一旦目标接口增加方法,代理对象和目标对象都要进行相应的修改,增加维护成本。
public interface UserDao {
public int add(int a,int b);
public String update(String name);
}
public class UserDaoImpl2 implements UserDao {
@Override
public int add(int a, int b) {
System.out.println("UserDaoImpl 2--add执行了");
return a+b;
}
@Override
public String update(String name) {
System.out.println("UserDaoImpl 2--update执行了");
return name;
}
}
public class UserDaoStaticProxy implements UserDao{
public UserDao userdao;
public UserDaoStaticProxy(UserDao userdao) {
this.userdao = userdao;
}
public static void main(String[] args) {
UserDaoImpl2 userDao2 = new UserDaoImpl2();
UserDaoStaticProxy udsp = new UserDaoStaticProxy(userDao2);
System.out.println("Static Proxy add result: "+udsp.add(1, 2));
System.out.println("===================================");
System.out.println("Static Proxy update result: "+udsp.update("hello shanghai"));
}
@Override
public int add(int a, int b) {
//增强
System.out.println("UserDaoStaticProxy--add执行了");
userdao.add(a, b);
return a+b;
}
@Override
public String update(String name) {
//增强
System.out.println("UserDaoStaticProxy--update执行了");
userdao.update(name);
return name;
}
}
2.动态代理(JDK动态代理):
为解决静态代理对象必须实现接口的所有方法的问题,Java给出了动态代理,动态代理具有如下特点:
1.Proxy对象不需要implements接口;
2.Proxy对象的生成利用JDK的Api,在JVM内存中动态的构建Proxy对象。
* Proxy.newProxyInstance()
* 三个参数解析:
* 第一: 需要实现增强类的加载器,这里指的是UserDaoImpl
* 第二: 需要增强的类的接口数组,这里只有一个UserDao
* 第三: 实现了InvocationHandler
接口的类,这里面进行增强操作,
* 多种方式: 1 匿名内部类
* 2 正常类实现InvocationHandler接口
public interface UserDao {
public int add(int a,int b);
public String update(String name);
}
public class UserDaoImpl implements UserDao {
@Override
public int add(int a, int b) {
System.out.println("UserDaoImpl--add执行了");
return a+b;
}
@Override
public String update(String name) {
System.out.println("UserDaoImpl--update执行了");
return name;
}
}
public class UserDaoProxy {
public static void main(String[] args) {
Class<?>[] interfaces = {UserDao.class};
/*
* Proxy.newProxyInstance()
* 三个参数解析:
* 第一: 需要实现增强类的加载器,这里指的是UserDaoImpl
* 第二: 需要增强的类的接口数组,这里只有一个UserDao
* 第三: 实现了InvocationHandler接口的类,这里面进行增强操作,
* 多种方式: 1 匿名内部类
* 2 正常类实现InvocationHandler接口
* */
//1 匿名内部类
// UserDao newProxyInstance = (UserDao)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader(), interfaces , new InvocationHandler() {
//
// @Override
// public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//
// //之前增强
// System.out.println("增强方法之前执行了..."+method.getName()+" 执行参数为: "+Arrays.toString(args));
// //增强方法执行
// Object invoke = method.invoke(new UserDaoImpl(), args);
//
// //之后增强
// System.out.println("增强方法之后执行了..."+" 返回为: "+invoke);
//
// return invoke;
// }
// });
//2 正常类实现InvocationHandler接口
ProxyHandler proxyHandler = new ProxyHandler(new UserDaoImpl());
UserDao newProxyInstance = (UserDao)Proxy.newProxyInstance(UserDaoImpl.class.getClassLoader()
, interfaces
, proxyHandler);
newProxyInstance.add(12, 1);
}
}
class ProxyHandler implements InvocationHandler{
public Object obj;
public ProxyHandler(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//之前增强
System.out.println("增强方法之前执行了..."+method.getName()+" 执行参数为: "+Arrays.toString(args));
//增强方法执行
Object invoke = method.invoke(obj, args);
//之后增强
System.out.println("增强方法之后执行了..."+" 返回为: "+invoke);
return invoke;
}
}
3.动态代理(CGLIB动态代理):
对于未实现接口的普通对象,需要代理就需要CGLIB(Code Generation Library)动态代理
原理:通过构建一个子类对象,实现对该对象的代理,需要目标对象不能是final类,且方法不能为finalh或static。
CGLIB需要依赖jar包:
maven依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.10</version>
</dependency>
public class UserCGLIBService {
public void execute() {
System.out.println("修改管理系统数据。");
}
public String getName(String name) {
System.out.println("查看管理系统数据。");
return name;
}
}
public class UserCGLIBProxy implements MethodInterceptor{
// public Object obj;
//
// public UserCGLIBProxy(Object obj) {
// this.obj = obj;
// }
//
// //给目标对象创建一个代理对象进行配置
// public Object getConfig() {
// //工具类
// Enhancer en = new Enhancer();
// //设置父类
// en.setSuperclass(obj.getClass());
// //设置回调函数
// en.setCallback(this);
// //创建子类代理对象
// return en.create();
// }
/*
* intercept()的参数:
* obj 表示增强的对象,即实现这个接口类的一个对象
* method 表示要被拦截的方法
* args 表示要被拦截的参数
* proxy 表示要触发父类的方法对象
* */
@Override
public Object intercept(Object object, Method method, Object[] arg2, MethodProxy arg3) throws Throwable {
//之前增强
System.out.println("增强之前执行了操作.方法:"+method.getName()+" 参数: "+Arrays.toString(arg2));
//增强方法执行
// Object invoke = method.invoke(object,arg2);
Object invoke = methodProxy.invokeSuper(object, arg2);
//之后增强
System.out.println("增强之后执行了操作.返回: "+invoke);
return invoke;
}
}
public class TestCGLIBProxy {
public static void main(String[] args) {
// UserCGLIBService userCGLIBService = new UserCGLIBService();
// UserCGLIBProxy userCGLIBProxy = new UserCGLIBProxy(userCGLIBService);
// //代理
// UserCGLIBService proxy = (UserCGLIBService)userCGLIBProxy.getConfig();
Enhancer en = new Enhancer();
//设置父类,指的是需要增强的类-->UserCGLIBService
en.setSuperclass(UserCGLIBService.class);
//设置回调函数,需要指定增强类-->UserCGLIBProxy
en.setCallback(new UserCGLIBProxy());
//创建子类代理对象,需要强转为 --> UserCGLIBService
UserCGLIBService proxy = (UserCGLIBService)en.create();
proxy.execute();
proxy.getName("Shanghai");
}
}