版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/shadowcw/article/details/83003628
代理的理解
代理(Proxy)是一种设计模式,提供了对目标对象另一种访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在实现目标对象功能的基础上,增强额外的功能操作,即扩展目标对象的功能。
代理的分类:1、静态代理 2、动态代理 3、Cjlib代理
静态代理
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者是继承相同父类
接口
package com.linewell.staticproxy;
public interface IUserDao{
public void save();
}
目标对象
package com.linewell.staticproxy;
public class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("我是目标对象保存的方法");
}
}
代理对象
package com.linewell.staticproxy;
public class UserDaoProxy implements IUserDao {
//接收保存目标对象
private IUserDao iUserDao;
public UserDaoProxy(IUserDao iUserDao){
this.iUserDao=iUserDao;
}
@Override
public void save() {
System.out.println("开始事物。。。。");
iUserDao.save();
System.out.println("执行事物。。。。");
}
}
测试类
package com.linewell.staticproxy;
public class App {
public static void main(String[] args) {
//创建目标对象
UserDao userDao=new UserDao();
//把目标对象传给代理对象
UserDaoProxy userDaoProxy=new UserDaoProxy(userDao);
userDaoProxy.save();
}
}
优点:在不改变目标对象的前提下,对目标对象进行扩展。
缺点:目标对象和代理对象都要实现相同的接口,如果说没有接口,那么就无法使用静态代理。
动态代理
也叫jdk代理,接口代理,代理对象不需要实现接口,代理的对象的生成是利用jdk的API通过反射的机制动态生成的。
反射:反射机制在运行状态中,对于任何一个类,可以知道他的所有属性和方法,对于任何一个对象,可以调用他的任意一个方法与属性
代理类:
package com.linewell.dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory implements InvocationHandler{
//定义一个目标对象
private Object target;
//给目标对象创建代理对象
public ProxyFactory(Object target) {
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("------------------before------------------");
Object returnValue= method.invoke(target, args);
System.out.println("------------------after------------------");
return returnValue;
}
//创建获取代理的方法
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
测试类:
package com.linewell.dynamicproxy;
import com.linewell.staticproxy.IUserDao;
import com.linewell.staticproxy.UserDao;
public class App {
public static void main(String[] args) {
//创建目标对象
IUserDao iUserDao=new UserDao();
System.out.println(iUserDao.getClass());
iUserDao.save();
//给目标对象创建代理对象
IUserDao proxy =(IUserDao)new ProxyFactory(iUserDao).getProxyInstance();
System.out.println(proxy.getClass());
proxy.save();
}
}
总结:代理对象不需要实现接口,但是目标对象一定要实现接口,否则不能用动态代理。
Cjlib代理
上面的静态代理和动态代理模式都是要求目标对象是实现一个接口的目标对象,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候就可以使用以目标对象子类的方式类实现代理,这种方法就叫做:Cglib代理,Cglib代理,也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能的扩展.
原理是通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。,但因为采用的是继承,所以不能对final修饰的类进行代理。
目标类:
package com.linewell.cjlib;
public class Cat {
public void eat(){
System.out.println("猫会钓鱼。。。。");
}
public void run(){
System.out.println("猫会上树。。。。");
}
}
代理类:
package com.linewell.cjlib;
import net.sf.cglib.proxy.Callback;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CatProxy implements MethodInterceptor{
//在内存中创建一个全新的类 没有类型 Enhancer类是CGLib中的一个字节码增强器
private Enhancer enhancer = new Enhancer();
//创建代理对象的方法
public Object createProxyObject(Class clazz){
enhancer.setSuperclass(clazz);
enhancer.setCallback(this);
//通过字节码技术动态创建子类实例
Object o=enhancer.create();
return o;
}
//intercept()方法拦截所有目标类方法的调用
//o表示目标类的实例
//method为目标类方法的反射对象
//MethodProxy为生成的代理类对方法的代理引用。
@Override
public Object intercept(Object o, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("前置代理");
Object obj = proxy.invokeSuper(o, args);//调用类目标类方法
System.out.println("后置代理");
return obj;
}
}
测试类:
package com.linewell.cjlib;
public class App {
public static void main(String[] args) {
CatProxy catProxy = new CatProxy();
Cat cat = new Cat();
cat =(Cat) catProxy.createProxyObject(cat.getClass());
cat.eat();
}
}