Day30-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\annotation\Proxy

反射

image-20251103144325959

package Basic.src.com.reflect;

import org.junit.Test;

import java.lang.reflect.Method;

public class Test4Method {
    @Test
    public void testGetMethhod() throws Exception {
        //1.反射第一步:先得到Class对象
        Class cat = Cat.class;
        //2.获取类的全部成员方法
        Method[] methods = cat.getDeclaredMethods();
        //3.遍历这个数组中的每个方法对象
        for (Method method : methods) {
            System.out.println(method.getName()+"------------"
                    +method.getParameterCount()+"------------"
                    +method.getReturnType());
        }

        //4.获取某个方法对象
        Method run = cat.getDeclaredMethod("run");//拿run(),无参的
        System.out.println(run.getName()+"------------"
        +run.getParameterCount()+"------------"
        +run.getReturnType());
        Cat cat1 = new Cat();
        run.setAccessible(true);//暴力反射public void run()即使是private也可以访问
        Object rs = run.invoke(cat1);//调用方法
        System.out.println(rs);//null

        System.out.println("====================================");

        Method eat = cat.getDeclaredMethod("eat", String.class);
        System.out.println(eat.getName()+"------------"
        +eat.getParameterCount()+"------------"
        +eat.getReturnType());
        eat.setAccessible(true);//private String eat(String name)
        String es = (String)eat.invoke(cat1,"鱼");
        System.out.println(es);//耄耄最爱食:鱼
        System.out.println(eat);//private java.lang.String Basic.src.com.reflect.Cat.eat(java.lang.String)
    }
}

image-20251103151446290

image-20251103151455593

image-20251103151508057

package Basic.src.com.reflect;

import org.junit.Test;

public class Test5Frame {
    @Test
    public void save() throws Exception {
        Student s1 = new Student("哈基滨", 22, '公', 185.3, "唱跳rap");
        Teacher t1 = new Teacher("南北绿豆", 999.9);

        //需求:把任意对象的字段名称和其对应的值等信息,保存到文件中去
        ObjectFrame.saveObject(s1);
        ObjectFrame.saveObject(t1);
    }
}
package Basic.src.com.reflect;

import java.io.FileOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;

public class ObjectFrame {
    //目标:保存任意对象的字段和其数据到文件中去
    public static void saveObject(Object obj) throws Exception {
        PrintStream ps = new PrintStream(new FileOutputStream("Basic\\src\\data.txt",true));
        //1.obj是任意对象,到底有多少个字段要保存。
        Class<?> c = obj.getClass();
        String cName = c.getSimpleName();
        ps.println("------------------"+cName+"------------------");
        //2.从这个类中提取它的全部成员变量
        Field[] fields = c.getDeclaredFields();
        //3.遍历每个成员变量
        for (Field field : fields) {
            //4.拿到成员变量的名字
            String name = field.getName();
            //5.拿到这个成员变量在对象中的数据
            field.setAccessible(true);//授权
            String value = field.get(obj)+"";//+""转为String类型
            ps.println(name+"="+value);
        }
        ps.close();
    }
}

image-20251103160728640

注解

注解本质上接口,继承了annotation

image-20251103164346221

package Basic.src.com.annotation;

@MyTest1(aaa="牛魔王",ccc={"HTML","JAVA"})
@MyTest2("孙悟空")//当只有一个未默认化的属性并且叫value,那么value可以省略
public class AnnotationTest1 {

    @MyTest1(aaa="铁山公主",bbb=false,ccc={"Python","前端","Java"})
    public void test1(){
        System.out.println("test1");
    }
    public static void main(String[] args) {
        //执行后会把上面的注解从java文件编译为class后缀的文件
        //"C:\Users\Lenovo\Desktop\note\code\JavaSE\out\production\JavaSE\Basic\src\com\annotation\MyTest1.class"
    }
}
package Basic.src.com.annotation;

/**
 * 自定义注解
 */

public @interface MyTest1 {
    String aaa();
    boolean bbb() default true;
    String[] ccc();
}
package Basic.src.com.annotation;

public @interface MyTest2 {
    String value();//特殊属性
    int age() default 0;
}

元注解

指的是:修饰注解的注解

@Target @Retention

image-20251103165148897

package Basic.src.com.annotation;

/*
* 元注解
* */
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.TYPE,ElementType.METHOD})//当前被修饰的注解只能被用在类上
@Retention(RetentionPolicy.RUNTIME)//只在运行阶段,常用
public @interface MyTest3 {
}
package Basic.src.com.annotation;

/*
 * 元注解
 * */
@MyTest3
public class AnnotationTest2 {
    //@MyTest3报错,这个是成员变量
    private String name;
    @MyTest3//不报错,这个是方法
    public void test(){

    }
}

image-20251103165937298

package Basic.src.com.annotation;

import org.junit.Test;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;

public class AnnotationTest3 {
    @Test
    public void parseClass() {
        //1.先得到class类对象
        Class<Demo> c = Demo.class;
        //2.解析上面的注解
        //判断这个类上面是不是包含了某个注解
        if(c.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填进去的注解类型
            MyTest4 myTest4 =
                    c.getDeclaredAnnotation(MyTest4.class);//就是Demo类里面有没有MyTest4这个注解
            System.out.println(myTest4.value());
            System.out.println(myTest4.aaa());
            System.out.println(Arrays.toString(myTest4.bbb()));
        }
        Annotation[] da = c.getDeclaredAnnotations();

        for (Annotation annotation : da) {

        }
    }

    @Test
    public void parseMethod() throws Exception {
        //1.先得到class类对象
        Class<Demo> c = Demo.class;
        Method m = c.getDeclaredMethod("test1");
        //2.解析上面的注解
        //判断这个"test1"测试方法对象上面是不是包含了某个注解
        if(m.isAnnotationPresent(MyTest4.class)){//MyTest4.class)是填进去的注解类型
            MyTest4 myTest4 =
                    c.getDeclaredAnnotation(MyTest4.class);//就是Demo类里面有没有MyTest4这个注解
            System.out.println(myTest4.value());
            System.out.println(myTest4.aaa());
            System.out.println(Arrays.toString(myTest4.bbb()));
        }
    }
}
package Basic.src.com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface MyTest4 {
    String value();
    double aaa() default 100;
    String[] bbb();
}
package Basic.src.com.annotation;
@MyTest4(value="蜘蛛精",aaa=99.5,bbb={"至尊宝","黑马"})
public class Demo {
    @MyTest4(value="哈基滨",aaa=66.6,bbb={"叮咚鸡","大狗嚼嚼嚼"})
    public void test1(){
        System.out.println("test1");
    }
}

image-20251103184226467

package Basic.src.com.annotation;


import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 目标:模拟Junit框架的设计
 */

public class AnnotationTest4 {
    //@MyTest
    public void test1(){
        System.out.println("test1");
    }
    @MyTest
    public void test2(){
        System.out.println("test2");
    }
    public void test3(){
        System.out.println("test3");
    }
    @MyTest
    public void test4(){
        System.out.println("test4");
    }
    public static void main(String[] args) throws InvocationTargetException, IllegalAccessException {
        AnnotationTest4 a = new AnnotationTest4();
        //实现启动程序
        //1.得到class对象
        Class<AnnotationTest4> c = AnnotationTest4.class;
        //2.提取这个类中的全部成员方法
        Method[] Methods = c.getDeclaredMethods();
        //3.遍历这个数组中的每个方法,看方法是是否存在
        //触发该方法的执行
        for (Method method : Methods) {
            if(method.isAnnotationPresent(MyTest.class)){
                //说明当前方法上存在该注解,触发该方法执行
                method.setAccessible(true);
                method.invoke(a);
                // Method.invoke() 方法时,括号中第一个参数需要传入的是调用该方法的对象实例(即方法所属的对象),其作用是指定 “在哪个对象上执行当前方法”。
            }
        }
    }
}
package Basic.src.com.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyTest {
}

动态代理

package Basic.src.com.annotation.Proxy;

public class BigStar implements Star {// implements Star是生成代理的约定{
    private String name;

    public BigStar(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String sing(String name) {
        System.out.println(this.name + "正在唱:" + name);
        return "thank you!";
    }
    public void dance(){
        System.out.println(this.name+"正在唱跳rap");
    }
}
package Basic.src.com.annotation.Proxy;

public interface Star {
    //先声明哪些方法要被代理
    String sing(String name);
    void dance();
}
package Basic.src.com.annotation.Proxy;

public class BigStar implements Star {// implements Star是生成代理的约定{
    private String name;

    public BigStar(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String sing(String name) {
        System.out.println(this.name + "正在唱:" + name);
        return "thank you!";
    }
    public void dance(){
        System.out.println(this.name+"正在唱跳rap");
    }
}
package Basic.src.com.annotation.Proxy;

public interface Star {
    //先声明哪些方法要被代理
    String sing(String name);
    void dance();
}
package Basic.src.com.annotation.Proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtil {
    public static Star createProxy(BigStar bigStar){
        Star starProxy = (Star) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(),
                new Class[]{Star.class}, new InvocationHandler() {//创建一个实现了 Star 接口的动态代理对象 starProxy
            //ProxyUtil 是你自己编写的类(位于 Basic.src.com.annotation.Proxy 包下),它的类加载器是 应用类加载器(AppClassLoader),负责加载用户编写的类(包括你的 Star 接口、BigStar 类等)。
                    //因此,ProxyUtil 的类加载器与 Star 接口的类加载器是同一个(或存在父子关系,符合双亲委派模型),它们属于同一个 “命名空间”。

                    @Override //回调方法
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //我们的代理对象要做的事情
                        //Object proxy 代理对象本身:starProxy 对象本身
                        //Method method 调用的什么函数,比如sing dance
                        //Object[] args 存储了客户端调用代理对象方法时传入的实际参数值,调用的比如sing方法里面的参数
                        if(method.getName().equals("sing")){
                            System.out.println("准备话筒,收钱");
                            //return method.invoke(bigStar,args);//args指的可能是唱哪首歌对应的参数
                        }else if(method.getName().equals("dance")){
                            System.out.println("准备场地,收钱");
                            //return method.invoke(bigStar,args);
                        }else {
                            //return method.invoke(bigStar,args);
                        }
                        return method.invoke(bigStar,args);//调用BigStar里面的该method对应的方法
                    }
                });//创建代理Proxy.newProxyInstance
        /*
        * ClassLoader loader,指定一个类加载器,生成一个代理类(固定)
           Class<?>[] interfaces,指定生成的代理长什么样,有什么方法,接收多个数组(接口数组里面的方法就可以被接收)
           InvocationHandler h指定生成的代理对象要干什么事情,代理干什么事情是由这个决定的
        * */
        return starProxy;
    }
}
package Basic.src.com.annotation.Proxy;

public class TestStar {
    public static void main(String[] args) {
        BigStar s = new BigStar("杨超越");
        Star starProxy = ProxyUtil.createProxy(s);//ProxyUtil类是我们自己编写的,里面有createProxy方法
        //创建代理对象,把s传进去,这个工具类就为杨超越类创建了一个代理对象
        String rs = starProxy.sing("好日子");//这里的sing方法会调用代理ProxyUtil类中的invoke方法,这里是接口回调
        System.out.println(rs);
        starProxy.dance();
    }
}

image-20251103201537507

image-20251103201555573

改造

package Basic.src.com.annotation.Proxy.Exercise;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyUtil {//代理对应规则
    public static UserService createUserService(UserService userService){
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(ProxyUtil.class.getClassLoader(), new Class[]{UserService.class},
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        if(method.getName().equals("login")||method.getName().equals("deleteUsers")||method.getName().equals("selectUsers")){
                            long startTime = System.currentTimeMillis();
                            Object rs = method.invoke(userService, args);
                            long endTime = System.currentTimeMillis();
                            System.out.println(method.getName()+"方法执行耗时"+(endTime-startTime)+"ms");
                            return rs;
                        }else{
                            Object rs = method.invoke(userService, args);
                            return rs;
                        }
                    }
                });
        return userServiceProxy;
    }
}
package Basic.src.com.annotation.Proxy.Exercise;

public interface UserService {
    //登录功能
    void login(String name,String password)throws Exception;
    //删除用户
    void deleteUsers()throws Exception;
    //查询用户,返回数组的形式
    String[] selectUsers()throws Exception;
}
package Basic.src.com.annotation.Proxy.Exercise;

public class UserServiceimpl implements UserService {
    @Override
    public void login(String name, String password) throws Exception {
        if("admin".equals(name) && "123456".equals(password)){
            System.out.println("登录成功,欢迎光临本系统");
        }else{
            System.out.println("登录失败,用户名或密码错误");
        }
        Thread.sleep(1000);
    }

    @Override
    public void deleteUsers() throws Exception {
        System.out.println("成功删除了一万个用户");
        Thread.sleep(1500);
    }

    @Override
    public String[] selectUsers() throws Exception {
        System.out.println("查询出了三个用户");
        String[] names = {"张三","李四","王五"};
        Thread.sleep(500);
        return names;
    }
}
package Basic.src.com.annotation.Proxy.Exercise;

import java.lang.reflect.Proxy;
import java.util.Arrays;

public class Test {
    public static void main(String[] args) throws Exception {
        //1.创建用户业务对象
        //UserService userService = new UserServiceimpl();//接口是 “类” 的一种特殊形式,这个没有计时功能
        UserService userService = ProxyUtil.createUserService(new UserServiceimpl());

        //2.调用用户业务的功能
        userService.login("admin","123456");//下面都是代理的代码
        System.out.println("===========================");

        userService.deleteUsers();
        System.out.println("===========================");

        String[] names = userService.selectUsers();
        System.out.println("查询到的用户是:"+ Arrays.toString(names));
        System.out.println("===========================");
    }
}
posted @ 2025-11-03 22:16  David大胃  阅读(9)  评论(0)    收藏  举报