标签:target 对象 Object 代理 模式 proxy 设计模式 public
代理模式
是什么?
1.为一个对象提供一个替身,一口控制对这个对象的访问,里通过代理对象访问目标对象,
这样做的好处是,可以在目标对象的基础上,增强额外的功能操作,即扩展目标对象的功能
2.被代理的对象可以是远程对象、创建开销大的对象、或者需要安全控制的对象
3.代理模式有不同的形式,主要有静态代理、动态代理(jdk代理、接口代理)、cglib代理(可以在内存中动态创建
对象,而不需要实现接口)
静态代理
静态代理在使用是,需要定义接口或者父类,被代理对象(目标对象)与代理对象一起实现相同的接口或者继承相同的类.
静态代理优缺点
优点:在不修改目标对象功能的前提下,能通过代理对象实现对目标对象功能的扩展
缺点:因为代理对象需要和目标对象实现或者继承相同的接口,所以会有很多代理类,一旦目标类有所变化,代理类也有可能要修改
package aa.proxy.a1;
public interface ITeacherDao {
public void teach();
}
package aa.proxy.a1;
public class TeachDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("ITeacherDao implements 子类 ;teach");
}
}
package aa.proxy.a1;
public class TeacherProxy implements ITeacherDao{
private ITeacherDao dao;
//有两种方式 1.构造器 2.作为类的属性设置set方法
@Override
public void teach() {
System.out.println("代理开始");
dao.teach();
System.out.println("代理结束");
}
public void setDao(ITeacherDao dao) {
this.dao = dao;
}
}
package aa.proxy.a1;
public class TeachCase {
public static void main(String[] args) {
ITeacherDao dao = new TeachDao();
TeacherProxy daoProxy = new TeacherProxy();
daoProxy.setDao(dao);
daoProxy.teach();
}
}
动态代理
1.代理对象不需要实现接口,但是要实现接口,否则不能使用动态代理
2.代理对象的生成,是利用jdk的API,动态的在内存中构建对象
3.动态代理也叫jdk代理、接口代理
4.代理类所在的包 java.lang.reflect.Proxy
5.jdk实现代理只要使用newProxyInstance方法,但是该方法许哟啊接受三个参数
static Object newProxyInstance(ClassLoad loader,Class<?>[] interfaces,InvocationHander hander)
package aa.proxy.a2;
public interface ITeacherDao {
public void teach();
public String say(String name);
}
package aa.proxy.a2;
public class TeachDao implements ITeacherDao{
@Override
public void teach() {
System.out.println("ITeacherDao implements 子类 ;teach");
}
@Override
public String say(String name) {
return "hello "+name;
}
}
package aa.proxy.a2;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class TeachDaoJDKProxy {
private Object target;
public TeachDaoJDKProxy(Object target) {
this.target = target;
}
public Object getJDKProxyInstance() {
/**
* ClassLoad loader:指当前目标对象使用的类加载器,获取加载器的方法固定
* Class<?>[] interfaces:目标对象实现的接口类型,使用泛型的接口类型,使用泛型方法确认类型
* InvocationHander hander:处理器,执行目标方法的方法时,会触发处理器方法,会吧当前执行的目标对象方法作为参数转入
*/
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 returnValue = method.invoke(target, args);
// System.out.println(returnValue);
return returnValue;
}
});
}
}
package aa.proxy.a2;
public class TeachCase {
public static void main(String[] args) {
ITeacherDao dao = new TeachDao();
ITeacherDao proxyInstance = (ITeacherDao) new TeachDaoJDKProxy(dao).getJDKProxyInstance();
System.out.println(proxyInstance.getClass());
proxyInstance.teach();
String s = proxyInstance.say("zs");
System.out.println(s);
}
}
cglib代理
1)静态代理和JDK代理模式都要求目标对象实现一个接口,但是有时候目标对象只是一个单独的对象,并
没有实现任何接口,这个时候可使用目标对象子类来实现代理
2)cglib代理也叫子类代理,他是在内存中创建一个子类对象从而实现对目标对象功能扩展
3)cglib是一个强大的高性能的代码生成包,他可以 在运行时期扩展Java类与实现Java接口,它广泛的
被许多AOP的框架使用,例如SpringAOP,实现方法拦截
4)在AOP编程中如何选择代理模式
I:目标对象许哟啊实现接口,JDK代理
II:目标对象不需要实现接口,用cglib
5)cglib包底层是通过字节码处理框架ASM来转换字节码并生成新的类
Cglib代理模式 实现步骤
1)引入Cglib需要使用的jar包
asm.jar
asm-commons.jar
asm-tree.jar
cglib-2.2.jar
2)在内存动态构建子类,注意代理的类不能是 final的。否则报错
3)目标对象的方法如果是final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法
package aa.proxy.a3;
public class TeachDao {
public void teach() {
System.out.println("ITeacherDao implements 子类 ;teach");
}
public String say(String name) {
return "hello "+name;
}
}
package aa.proxy.a3;
import java.lang.reflect.Method;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxyTeachDao implements MethodInterceptor{
private Object target;
public CglibProxyTeachDao(Object target) {
this.target = target;
}
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
return arg1.invoke(target, arg2);
}
//返回代理对象,是target的代理对象
public Object getProxyInstance() {
//创建一个工具类
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(target.getClass());
//设置回调函数
enhancer.setCallback(this);
//创建子类代理对象
return enhancer.create();
}
}
package aa.proxy.a3;
public class TeachCase {
public static void main(String[] args) {
TeachDao dao = new TeachDao();
TeachDao cglibProxyTeachDao = (TeachDao) new CglibProxyTeachDao(dao).getProxyInstance();
cglibProxyTeachDao.teach();
String ss = cglibProxyTeachDao.say("zs");
System.out.println(ss);
}
}
标签:target,对象,Object,代理,模式,proxy,设计模式,public 来源: https://blog.csdn.net/weixin_39472101/article/details/121454910
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。