实现代理的目的就是,要把附加功能从业务功能代码中抽取出来,即创建代理类,这个代理类也要实现业务代码接口里的所有方法,然后在启动类中,通过创建代理类对象,来使用相对应的方法。无论动态代理还是静态代理,代理类都要和目标类实现相同的接口。每一次要访问目标类中的功能的时候,都是通过访问代理类中的功能来间接访问目标类中的功能,目标对象能做什么,代理对象也要能做什么,通过代理对象来控制目标对象实现的过程,从而加入一些而外的功能来实现代码增强的效果,也就是在目标类代码不改变的情况下,通过代理对象,来间接访问目标对象。
静态代理类的缺点:静态代理类实现了和目标类相同的接口,静态代理类里所对应的目标对象也是完全写死的,这样做,使得代码不具备灵活性。
动态代理类:在使用的过程中,通过调用jdk中的api来动态的为我们的创建目标类所需要的代理类
下面来看一下具体的构建
先看一下,静态代理的实现
这是接口:
package com.dtguigu.spring;
public interface Calculator {
int add(int i, int j);
int sub(int i, int j);
int mul(int i, int j);
int div(int i, int j);
}
这是目标类:
package com.dtguigu.spring;
public class CalculatorImpl implements Calculator {
@Override
public int add(int i, int j) {
int result=i+j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int sub(int i, int j) {
int result=i-j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int mul(int i, int j) {
int result=i*j;
System.out.println("方法内部,result:"+result);
return result;
}
@Override
public int div(int i, int j) {
int result=i/j;
System.out.println("方法内部,result:"+result);
return 0;
}
}
这是静态代理类的实现
package com.dtguigu.spring;
public class CalculatorStaticProxy implements Calculator{
private CalculatorImpl target;
public CalculatorStaticProxy(CalculatorImpl target) {
this.target = target;
}
@Override
public int add(int i, int j) {
System.out.println("日志,方法:add,参数:"+i+","+j);
int result=target.add(i,j);
System.out.println("日志,方法:add,结果:"+result);
return result;
}
@Override
public int sub(int i, int j) {
System.out.println("日志,方法:sub,参数:"+i+","+j);
int result=target.sub(i,j);
System.out.println("日志,方法:sub,结果:"+result);
return result;
}
@Override
public int mul(int i, int j) {
System.out.println("日志,方法:mul,参数:"+i+","+j);
int result=target.mul(i,j);
System.out.println("日志,方法:mul,结果:"+result);
return result;
}
@Override
public int div(int i, int j) {
System.out.println("日志,方法:div,参数:"+i+","+j);
int result=target.div(i,j);
System.out.println("日志,方法:div,结果:"+result);
return result;
}
}
这是测试类
package com.atguigu.proxy;
import com.dtguigu.spring.Calculator;
import com.dtguigu.spring.CalculatorImpl;
import com.dtguigu.spring.CalculatorStaticProxy;
import com.dtguigu.spring.ProxyFactory;
import org.junit.Test;
public class ProxyTest {
/*
*动态代理有两种:
* 1.jdk动态代理,要求必须有接口,最终生成的代理类和目标类实现相同的接口
* 在com.sun.prixy包下,类名为$proxy2
* 2.cdlib动态代理,最终生成的代理类会继承目标类,
* 并且和目标类在相同的包下
*
*
* */
@Test
public void testProxy(){
CalculatorStaticProxy proxy = new CalculatorStaticProxy(new CalculatorImpl());
proxy.add(5,2);
proxy.mul(5,2);
proxy.div(11,2);
//创建代理工厂,传入实体类
// ProxyFactory factory = new ProxyFactory(new CalculatorImpl());
//
// Calculator proxy = (Calculator) factory.getProxy();
// /*
// * 不知道其实现的类型,用接口类型来实现,获取代理对象
// *
// * */
// proxy.mul(1,47);
}
}
接下来,看动态代理类的实现,
package com.dtguigu.spring;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
//动态代理
public class ProxyFactory {
//首先要知道目标对象
private Object target;
public ProxyFactory(Object target) {
this.target = target;
}
/*
*无论动态代理还是静态代理,代理类都要和目标类实现相同的接口
* ClassLoader loader:指定动态加载生成的类加载器
* Class<?>[] interfaces:获取目标对象实现的所有接口的class对象的数组
* InvocationHandler h:设置代理类中的抽象方法如何重写的过程,
* 即代理类中如何重写接口中的抽象方法
*
*
* */
public Object getProxy(){
ClassLoader classLoader= target.getClass().getClassLoader();
Class<?>[] interfaces = target.getClass().getInterfaces();
InvocationHandler invocationHandler=new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
//invoke:代理对象该如何执行方法,proxy表示代理对象,
// method表示要执行的方法,args要执行方法的参数列表
Object result = null;
try {
System.out.println("[动态代理][日志] "+method.getName()+",参 数:"+ Arrays.toString(args));
//
result = method.invoke(target, args);//调用目标对象实现功能的过程,
System.out.println("[动态代理][日志] "+method.getName()+",结果:"+ result);
} catch (Exception e) {
e.printStackTrace();
System.out.println("[动态代理][日志] "+method.getName()+",异 常:"+e.getMessage());
} finally {
System.out.println("[动态代理][日志] "+method.getName()+",方法 执行完毕");
}
return result;
}
};
return Proxy.newProxyInstance(classLoader,interfaces,invocationHandler);
}
}
这是测试类的实现:
package com.atguigu.proxy;
import com.dtguigu.spring.Calculator;
import com.dtguigu.spring.CalculatorImpl;
import com.dtguigu.spring.CalculatorStaticProxy;
import com.dtguigu.spring.ProxyFactory;
import org.junit.Test;
public class ProxyTest {
/*
*动态代理有两种:
* 1.jdk动态代理,要求必须有接口,最终生成的代理类和目标类实现相同的接口
* 在com.sun.prixy包下,类名为$proxy2
* 2.cdlib动态代理,最终生成的代理类会继承目标类,
* 并且和目标类在相同的包下
*
*
* */
@Test
public void testProxy(){
// CalculatorStaticProxy proxy = new CalculatorStaticProxy(new CalculatorImpl());
// proxy.add(5,2);
// proxy.mul(5,2);
// proxy.div(11,2);
//创建代理工厂,传入实体类
ProxyFactory factory = new ProxyFactory(new CalculatorImpl());
Calculator proxy = (Calculator) factory.getProxy();
/*
* 不知道其实现的类型,用接口类型来实现,获取代理对象
*
* */
proxy.mul(1,47);
}
}
这是结果:
pom文件,两种实现方式都是一样的依赖
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<artifactId>Spring</artifactId>
<groupId>org.example</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>spring-proxy</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.3.RELEASE</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>RELEASE</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>