注解与代理模式

注解与代理模式

相关介绍

Annotation就是嵌入在代码中的标记,补充代码功能,可以修饰包,类,方法,变量
实际开发中,基于注解可以替换配置文件
框架 = 注解 + 反射 + 设计模式的集合

/**

  • 1,注解的自定义,参照SuppressWarnings来定义注解,
  • 2,注解的使用是施加在某个类上或是方法上,通过反射,可以读出注解中给出的值才有意义。
  • 3,元注解:
  •  Retention:指明修饰的注解的生命周期,有三种状态:
    
  •      SOURCE:javac指令编译后,在.class文件中不会保留这个注解,被编译器丢弃。
    
  •      CLASS:编译器编译后保留在.class文件当中,但是不会继续保留到执行时候,
    
  •  不存保留到内存当中,注解定义默认是CLASS
    
  •      RUNTIME:注解被加载到内存中,可以通过反射来读取
    
  •  Target:用于指定被修饰的注解可以修饰哪些程序元素
    
  •      TYPE:类,接口
    
  •      FIELD
    
  •      METHOD
    
  •      .
    
  •      .
    
  •      .
    

  •  Documented:表示所修饰的注解,被javadoc解析时保留进文档中
    
  •  Inherited:表示这个注解能被继承,父类有这个注解,子类上也会添加上这个注解
    

*/
public @interface MyAnnotation {
//这是注解的属性,而不是方法,采用方法的定义方式而已
String value() default "hello";
}

使用反射来获取注解信息

代理模式

静态代理

两个类实现同一个接口,代理类和目标对象的类型在编译时期就已经确定了,不利于程序拓展,
并且每个代理类只为一个接口服务,程序开发过程一定会出现很多代理。

public class ProxyTest {
    public static void main(String[] args) {
        //new一个代理类对象,传进去一个被代理类对象
        ProxyPerson proxyPerson = new ProxyPerson(new RealStar());
        //代理类对象干活
        proxyPerson.confer();
        proxyPerson.signContract();
        proxyPerson.order();
        //有些工作干不了
        proxyPerson.sing();
        proxyPerson.collectMoney();
    }
}
interface Star{
    void confer();//面基
    void signContract();//签合同
    void sing();//唱歌
    void collectMoney();//收钱
}
//被代理类
class RealStar implements Star{
    @Override
    public void confer() {

    }

    @Override
    public void signContract() {

    }

    @Override
    public void sing() {
        System.out.println("明星唱歌~~~~");
    }

    @Override
    public void collectMoney() {

    }
}
//代理类--经纪人
class ProxyPerson implements Star{
    private Star real;

    public ProxyPerson(Star real) {
        this.real = real;
    }

    @Override
    public void confer() {
        System.out.println("经纪人面基");
    }

    @Override
    public void signContract() {
        System.out.println("经纪人签合同");
    }

    public void order(){
        System.out.println("经纪人定票");
    }

    @Override
    public void sing() {
        real.sing();
    }

    @Override
    public void collectMoney() {
        System.out.println("经纪人收钱");
    }
}

动态代理

通过一个代理类完成全部代理功能
使用场合:
远程方法调用
调试

public class ProxyTest {
    /**
     * 1.jdk动态代理:要求必须有接口,最终生成的代理类在com.sun.proxy包下,类名为$proxy+数字
     * 2.cglib动态代理:可以不要接口,最终生成的代理类会继承被代理类,在同一个包下
     * 3.dooker zeeker 要用cglib动态代理,因为会在同一个包下。?????
     * @param args
     */
    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance可以转为Human,而不能转为SuperMan,
        // 否则,代理类与被代理类是一个类,只是借用被代理类的实现接口
        Human proxyInstance = (Human) ProxyFactory.getProxyInstance(superMan);
        //代理类中没有直接声明与代理类一样的方法,但是调用的确实被代理类的方法,
        //会自动执行被代理类的方法
        //只需要提供一个被代理类,就能实现这种动态代理!!!!
        String belief = proxyInstance.getBelief();
        System.out.println(belief);
        proxyInstance.eat("四川麻辣烫");
    }
}
interface Human{
    String getBelief();
    void eat(String food);
}
//被代理类
class SuperMan implements Human{
    @Override
    public String getBelief() {
        return "I believe I can fly!!";
    }

    @Override
    public void eat(String food) {
        System.out.println("我喜欢吃" + food);
    }
}
/**
 *  1.如何根据加载到内存中的被代理类,动态的创建代理类及其对象
 *  2.当通过代理的对象调用方法时,如何动态的调用被代理类中的同名方法
 *
 */
//我们使用工厂模式,创建一个工厂类,
class ProxyFactory{
    //调用此方法返回一个代理类对象,解决问题1
    public static Object getProxyInstance(Object object){
        //object指向被代理类的对象,这里不能返回Human,写死了,要用一个代理对象代理多个类
        //代理类的实例是通过这样的方式创建得到,类的加载器以及实现的接口都与被代理对象的一致
        //当通过代理的对象调用方法时,动态的调用被代理类中的同名方法
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(object);
        /**
         * 1.指定加载动态生成的代理类的类加载器,随便找一个,只要是系统类加载器就行,
         * 所以指定为被代理对象的.class来找到类加载器
         * 2.目标类与代理类实现的接口一样
         * 3.
         */
        
        return Proxy.newProxyInstance(object.getClass().getClassLoader(),object.getClass().getInterfaces(),handler);
    }
}
class MyInvocationHandler implements InvocationHandler{
    //使用被代理类的对象进行赋值
    private Object obj;

    public void bind(Object obj) {
        this.obj = obj;
    }

    //当通过代理类的对象调用方法a时,就会自动调用如下方法invoke
    //将被代理类要执行的方法a的功能声明在此
    //代理类的对象,代理类对象的方法
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        /**
         *  proxy:表示代理对象
         *  method:即为代理类对象调用的方法,此方法也作为被代理类对象调用的方法,来回切换
         *  args:表示要执行的方法的参数列表
         *  obj:被代理对象
         */

        //功能实现之前增加一。。。。
        //调用目标对象实现功能
        Object returnVal = method.invoke(obj, args);
        //功能实现之后增加二。。。能够实现AOP
        return returnVal;
    }
}
posted @   少女的杀手  阅读(112)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示