动态代理:
代理:这个概念是什么呢,比如我们交话费,交话费交给谁呢,这个收钱的是不是中国的三大运营商,但是我们普通人怎么去充值话费呢,这时我们是不不是需要去营业厅去交话费,营业厅输入我们的电话号码,和我们的金额,在运营商的账户中一充值我们手机就能够接收到了余额的信息了。这个充话费的过程就是属于代理,营业厅代理了我们去充值。
[](
这个过程产生的代码如下面所示
/**
* 定义个人的接口,
* 就比如人交话费
*/
public interface Person {
public void payBill();
}
//定义用户
public class User implements Person{
@Override
public void payBill() {
// 用户没有时间,不知道其他方式充值
System.out.println("充值移动号码话费:50元");
}
}
/**
* 代理商帮助用户充值
*/
public class Operators implements Person{
private User user;
public Operators(User user){
this.user = user;
}
@Override
public void payBill() {
System.out.println("营业厅充值话费");
this.user.payBill();
System.out.println("充值成功");
}
public static void main(String[] args){
Operators operators = new Operators(new User());
operators.payBill();
}
}
/**
* ~out
* 营业厅充值话费
* 充值移动号码话费:50元
* 充值成功
*/
上面就是整个静态代理的过程以及实现,下面来看动态代理。
动态代理(以下称代理),利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象)
(Using Java Reflection to create dynamic implementations of interfaces at runtime)。
代理的是接口(Interfaces),不是类(Class),更不是抽象类。
解决特定问题:一个接口的实现在编译时无法知道,需要在运行时才能实现
实现某些设计模式:适配器(Adapter)或修饰器(Decorator)
其实个人感觉在适配器方面和Aop中使用的动态代理还挺多的,个人感觉还是不太清晰,只是其中通过反射获取接口中的实现类通过Handler中持有的代理的实例target然后所有代理对象的方法都会通过invoke方法执行,
interface Person {
void walk();
void sayHello(String name);
}
class MyInvokationHandler implements InvocationHandler {
/*
执行动态代理对象的所有方法时,都会被替换成执行如下的invoke方法
其中:
proxy:代表动态代理对象
method:代表正在执行的方法
args:代表调用目标方法时传入的实参
*/
public Object invoke(Object proxy, Method method, Object[] args) {
System.out.println("----正在执行的方法:" + method);
if (args != null) {
System.out.println("下面是执行该方法时传入的实参为:");
for (Object val : args) {
System.out.println(val);
}
} else {
System.out.println("调用该方法没有实参!");
}
return null;
}
}
public class ProxyTest {
public static void main(String[] args)
throws Exception {
// 创建一个InvocationHandler对象
InvocationHandler handler=new MyInvokationHandler();
// 使用指定的InvocationHandler来生成一个动态代理对象
Person p=(Person)Proxy.newProxyInstance(Person.class.getClassLoader(), new Class[]{Person.class}, handler); // 调用动态代理对象的walk()和sayHello()方法
p.walk();
p.sayHello("孙悟空");
}
}
public class Test {
/**
* JDK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类,这两个类相互配合,入口是Proxy。
* Proxy有个静态方法:getProxyClass(ClassLoader, interfaces),只要你给它传入类加载器和一组接口,它就给你返回代理Class对象。
*/
public static void main(String[] args){
// 创建一个程序员
Programmer programmer = new Programmer();
// 创建kay bos
Person kayProgrammer = new KayProgrammer(programmer);
// kay bos 让程序员替写代码
kayProgrammer.doJob();
// 用program生成一个代理对象
Person programmerdoJob = (Person) Proxy.newProxyInstance(programmer.getClass().getClassLoader(), programmer.getClass().getInterfaces(), (proxy, method, args1) -> {
System.out.println("----执行方法"+method);
// 如果调用了doJob方法
if(args!=null){
System.out.println("下面是执行该方法时传入的实参为:");
for (Object val : args) {
System.out.println(val);
}
method.invoke(kayProgrammer,args);
}else{
System.out.println("调用该方法没有实参!");
}
return null;
});
programmerdoJob.doJob();
}
}
interface Person{
// 人干活
void doJob();
}
class Programmer implements Person{
@Override
public void doJob() {
System.out.println("程序员的工作是写代码");
}
}
// 这个KayProgrammer是个不写代码的公司的leader.
class KayProgrammer implements Person {
// 让程序员去写
private Programmer programmer;
public KayProgrammer(Programmer programmer) {
this.programmer = programmer;
}
// 这个KayProgrammer程序员写代码让自己看
public void notice(){
System.out.println("notice.... coding to me");
}
@Override
public void doJob() {
System.out.println("我是kay 我不想写代码 我让程序员去写");
// 让程序员写代码
programmer.doJob();
// 自己看代码
notice();
}
}
这样以来动态代理就清晰了许多,那么我们来模仿者JDK动态代理手写一个属于自己的动态代理 jdk动态代理生成对象的步骤如下以后再写:
1.获取被代理对象的引用,并且获取它所有的接口,反射获取
2.JDK动态代理类重新生成一个新的类,同时新的类要实现被代理类实现的所有接口
3.动态生成java代码,新加的业务逻辑方法有一定的逻辑代码调用(在代码中体现)
4.编译新生成的Java代码.class文件
5.重新加载到JVM中运行。