1 概念
代理:proxy 结构性模式中的代理模式
要调用目标对象的功能时:不是直接访问目标对象 而是通过代理对象 间接访问目标对象的功能:
对目标对象的功能进行扩展
代理对象:对目标对象的功能进行改进和加功
目标对象:功能被扩展的对象
2 静态代理
要求:
静态代理:为目标对象创建一个代理类:代理类需要关联目标对象 代理类和目标对象实现相同的接口/继承相同的父类
在代理类方法中调用目标对象的方法 在调用之前和之后可以加扩展的代码
目标对象和代理类 必须实现相同的接口或者相同的父类
准备
public interface WorkerInterface {
void work();
void smoke(String smokeLogo);
void sleep();
}
public class Worker implements WorkerInterface {
private String wname;
public Worker(String wname) {
this.wname = wname;
}
public void work(){
System.out.println("工人:"+wname+",开始工作了!");
}
public void smoke(String smokeLogo){
System.out.println("工人:"+wname+",正在吸烟,烟的牌子是"+smokeLogo+"!");
}
public void sleep(){
System.out.println("工人:"+wname+",正在休息!");
}
@Override
public String toString() {
return "Worker [wname=" + wname + "]";
}
}
package proxy;
public class Proxy {
public static void main(String[] args) {
// 4 创建目标对象
Worker worker = new Worker("张三");
// 5 创建代理对象 并关联目标
WorkerProxy wp = new WorkerProxy(worker);
// 6 调用代理对象的方法
wp.sleep();
wp.work();
wp.smoke("中华");
}
}
// 1 实现相同接口
class WorkerProxy implements WorkerInterface {
// 2 关联目标对象
private WorkerInterface worker;
public WorkerProxy(WorkerInterface worker) {
this.worker = worker;
}
// 3 在代理对象的方法中 调用目标对象的方法 在调用之前和之后可以加扩展的代码
@Override
public void work() {
worker.work();
System.out.println(worker + "辛苦了!");
System.out.println("*************************************");
}
@Override
public void smoke(String smokeLogo) {
System.out.println(worker + "吸烟有害健康!");
worker.smoke(smokeLogo);
System.out.println("*************************************");
}
@Override
public void sleep() {
System.out.println(worker + "劳逸结合!");
worker.sleep();
System.out.println(worker + "睡觉结束,满血复活!");
System.out.println("*************************************");
}
}
总结
优点:可以实现对目标对象功能的扩展
缺点:1 只能代理指定接口的实现类
2 不能对目标对象的特有功能进行扩展
3 动态代理(jdk代理)
概念
*动态代理:
* 1.不需要声明定义一个代理类
* 2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
* 3.动态代理也叫做:JDK代理
*
*通过java.lang.reflect. Proxy 的newProxyInstance方法在内存中动态生成目标对象的代理对象
*** 动物类 ***
package proxy;
public class Cat implements Animal{
public void eat(){
System.out.println("猫爱吃鱼!");
}
}
interface Animal{
void eat();
}
代理对象的工厂类:写法1:普通写法
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyF {
public static void main(String[] args) {
// 创建目标对象
Worker w = new Worker("林风");
// 创建工厂对象
ProxyFactory factroy = new ProxyFactory(w);
// 通过工厂对象动态获取一个代理对象
WorkerInterface wi = (WorkerInterface) factroy.getProxy();
wi.sleep();
wi.work();
wi.smoke("芙蓉王");
//创建工厂对象
ProxyFactory factroy2=new ProxyFactory(new Cat());
Animal a=(Animal)factroy2.getProxy();
a.eat();
}
}
// 1 定义一个代理类工厂对象:实现接口InvocationHandler
class ProxyFactory implements InvocationHandler {
// 2 定义引用记录目标对象:通过构造方法关联
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
// 3 定义方法: 通过Proxy的newProxyInstance方法动态的在内存中创建目标对象的代理对象
public Object getProxy() {
/**
* newProxyInstance三个参数
* 1 loader: 用哪个类加载器去加载代理对象
* 2 interfaces:动态代理类需要实现的接口
* 3 h:动态代理方法在执行时,会调用h里面的invoke方法去执行
**/
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
// 4 实现InvocationHandler的invoke方法:目标对象的每个方法被调用:此invoke方法发都会被调用一次
/**
* invoke三个参数
* 1 proxy:就是代理对象,newProxyInstance方法的返回对象
* 2 method:调用的方法
* 3 args:方法中的参数
**/
@Override
public Object invoke(Object obj, Method method, Object[] params) throws Throwable {
System.out.println(method + ":" + params + ":::方法执行前的扩展");
Object result = null;
result = method.invoke(target, params);
System.out.println(method + ":" + params + ":::方法执行后的扩展");
System.out.println("*******************************************");
return result;
}
}
代理对象的工厂类:写法2:匿名内部类来实现
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyF {
public static void main(String[] args) {
// 创建目标对象
Worker w = new Worker("林风");
// 创建工厂对象
ProxyFactory factroy = new ProxyFactory(w);
// 通过工厂对象动态获取一个代理对象
WorkerInterface wi = (WorkerInterface) factroy.getProxy();
wi.sleep();
wi.work();
wi.smoke("芙蓉王");
// 创建工厂对象
ProxyFactory factroy2 = new ProxyFactory(new Cat());
Animal a = (Animal) factroy2.getProxy();
a.eat();
}
}
class ProxyFactory {
// 定义引用记录目标对象:通过构造方法关联
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
// 定义方法: 通过Proxy的newProxyInstance方法动态的在内存中创建目标对象的代理对象
public Object getProxy() {
/**
* newProxyInstance三个参数
* 1 loader: 用哪个类加载器去加载代理对象
* 2 interfaces:动态代理类需要实现的接口
* 3 h:动态代理方法在执行时,会调用h里面的invoke方法去执行
**/
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
/**
* invoke三个参数
* 1 proxy:就是代理对象,newProxyInstance方法的返回对象
* 2 method:调用的方法
* 3 args:方法中的参数
**/
// 实现InvocationHandler的invoke方法:目标对象的每个方法被调用:此invoke方法发都会被调用一次
@Override
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
System.out.println(method + ":" + params + ":::方法执行前的扩展");
Object result = null;
result = method.invoke(target, params);
System.out.println(method + ":" + params + ":::方法执行后的扩展");
System.out.println("************************************************************");
return result;
}
});
}
}
总结
jdk代理:可以代理任意目标对象:但目标类必须实现接口
4 cglib代理
概念
* CGLIB代理:子类对象
* 在运行时期,在内存中动态的创建一个目标对象类的子类对象
* 被spring框架的aop使用:依赖的jar被融入到了spring-core的jar
* 先导入jar: spring-core-3.2.18.RELEASE.jar
* 优点:可以为所有对象动态创建代理对象::不需要目标对象实现接口
目标对象类
class Book{
public int add(int a,int b){
System.out.println(a+"+"+b+"="+(a+b));
return a+b;
}
}
代理工厂类
package proxy;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
public class ProxyF {
public static void main(String[] args) {
// 创建目标对象
Book b = new Book();
// 创建工厂对象
ProxyFactory factroy = new ProxyFactory(b);
// 通过工厂对象动态获取一个代理对象
Book bproxy = (Book) factroy.getProxy();
// 调用代理对象的方法;
System.out.println(bproxy.add(1, 2));
}
}
// 1 创建代理工厂类 实现接口MethedInterceptor
class ProxyFactory implements MethodInterceptor {
// 2 关联目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
// 3 创建方法获取代理对象
public Object getProxy() {
// 1 创建工具类
Enhancer eh = new Enhancer();
// 2 指定父类
eh.setSuperclass(target.getClass());
// 3 设置回调函数
eh.setCallback(this);
// 4 获取代理对象
return eh.create();
}
/**
* intercept四个参数
* 1 Object o:代理对象本身
* 2 Method method: 被代理对象的方法
* 3 Object[] objects:函数调用的参数
* 4 MethodProxy methodProxy:方法的代理
**/
// 4 实现intercep方法:目标对象的方法每次被调用 此方法都会被调用
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
System.out.println("cglib代理:::方法执行前的扩展代码");
Object result = null;
result = arg1.invoke(target, arg2);
System.out.println("cglib代理:::方法执行后的扩展代码");
return result;
}
}
总结
cglib代理:不需要目标类 实现接口