
尚硅谷传送门==>B站尚硅谷Java设计模式
❤❤❤感谢尚硅谷❤❤❤
最近开始计划学习一下设计模式了,加油!!!
代理模式:给一个对象提供副本,通过这个 副本对象 来控制 真实对象 的访问。那么就算是想要扩展新的内容或功能,在副本对象上修改即可.
(可理解为分身,可通过分身找到本体,对于分身的管理操作会影响到本体,)
被代理的对象可以是远程对象、创建开销大的对象或需要安全控制的对象
具体可分为3种:
静态代理
动态代理 (JDK代理、接口代理)
Cglib代理 (在内存动态的创建对象)
代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。
使用静态代理模式;在不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展;
但是由于代理对象需要与目标对象实现一样的接口,所以就要产生很多代理类;
如果说接口要增加方法,目标对象和代理对象都要增加方法实现.
案例:
代理和目标的共同接口UserDao
//接口 ,目标对象和代理对象都要实现;
public interface UserDao {
//添加用户方法;
public abstract void addUser();
}
目标RealUserDao
//目标;
public class RealUserDao implements UserDao{
@Override
public void addUser() {
System.out.println("目标对象说要添加用户");
}
}
代理ProxyUserDao
//代理;
public class ProxyUserDao implements UserDao{
//把目标聚合过来;
private UserDao target;
public ProxyUserDao(UserDao target) {
this.target = target;
}
@Override
public void addUser() {
System.out.println("静态代理开始-->");
target.addUser();
System.out.println("结束--->");
}
}
模拟客户端Client
public class Client {
public static void main(String[] args) {
ProxyUserDao proxyUserDao =new ProxyUserDao(new RealUserDao());
//通过代理对象,调用到目标对象的方法;
proxyUserDao.addUser();
}
}
只需要目标对象去实现接口即可 ; 代理对象不需要实现接口.
代理类所在的包:java.lang.reflect.Proxy
代理对象使用JDK的API,动态形式在内存中构建代理对象;
使用方法newProxyInstance( ) 时,
参数 :ClassLoader loader ;指定当前目标对象使用的类加载器;
参数: Class>[] interfaces : 目标对象实现的接口.
参数: InvocationHandler h) 执行目标对象方法时,触发事件发生器,会通过反射得到执行的目标对象方法.
public static Object newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h) throws IllegalArgumentException
接口UserDao
//接口 仅需要目标对象实现;
public interface UserDao {
//添加用户方法;
public abstract void addUser();
}
目标类RealUserDao
//目标;
public class RealUserDao implements UserDao{
@Override
public void addUser() {
System.out.println("目标对象说要添加用户");
}
}
代理类
//代理工厂;
public class ProxyFactory {
//维护目标对象;
private Object target;
//初始化;
public ProxyFactory(Object target) {
this.target = target;
}
//动态代理;
public Object getProxyInstance(){
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("动态代理/JDK代理");
Object invoke = method.invoke(target, args);
return invoke;
}
});
}
}
模拟客户端
public class Client {
public static void main(String[] args) {
//创建目标对象;
UserDao realUserDao = new RealUserDao();
//为目标对象 创建 代理对象;
UserDao proxyFactory= (UserDao)new ProxyFactory(realUserDao).getProxyInstance();
proxyFactory.addUser();
}
}
Cglib代理(子类代理)
在内存中构建一个子类对象 ; 实现对目标对象功能扩展.
Cglib百科
Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类.
注意代理的类不能定义为final,否则报错java.lang.IllegalArgumentException:
目标对象的方法若为final/static,就不会被拦截(不会执行目标对象额外的业务方法)
需要的maven依赖;
cglib cglib 3.2.11 org.ow2.asm asm-commons 7.1
类图原理
getInstance ( ) 方法为目标对象target创建代理对象;
重写的 intercept ( ) 方法,实现了对于目标对象的方法调用.
目标类RealUserDao
//目标类;
public class RealUserDao {
//添加用户;
public void addUser(){
System.out.println("用了Cglib的方式,无需使用接口");
System.out.println("添加用户的方法");
}
}
代理类ProxyFactory
//代理;
public class ProxyFactory implements MethodInterceptor {
//定义目标对象;
private Object target;
//初始化;
public ProxyFactory(Object target) {
this.target = target;
}
//返回 target的代理对象;
public Object getProxyInstance(){
//创建工具类;
Enhancer enhancer = new Enhancer();
//设置父类;
enhancer.setSuperclass(target.getClass());
//设置回调函数;
enhancer.setCallback(this);
//返回代理对象;
return enhancer.create();
}
//重写的 intercept () 方法,实现了对于目标对象的方法调用.
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开始Cglib代理模式");
Object invoke = method.invoke(target, objects);
System.out.println("Cglib代理模式==> 提交 <==");
return invoke;
}
}
模拟客户端
//模拟客户端;
public class Client {
public static void main(String[] args) {
//目标对象;
RealUserDao target =new RealUserDao();
//取到目标对象的 代理对象;
RealUserDao proxyFactory = (RealUserDao) new ProxyFactory(target).getProxyInstance();
//执行代理对象的方法;
proxyFactory.addUser();
}
}