• java反射,注解,动态代理学习(黑马程序员)


    1发射

    1.1 反射的用途:获取类的信息。

    能够将任意一个对象的属性名和属性值写到文件中去。不管这个对象有多少个属性,也不管这个对象的属性名是否相同。

    1.2反射的步骤:

    1.2.1获取类:

    public class Test1Class{
        public static void main(String[] args){
            Class c1 = Student.class;
            System.out.println(c1.getName()); //获取全类名
            System.out.println(c1.getSimpleName()); //获取简单类名
            
            Class c2 = Class.forName("com.itheima.d2_reflect.Student");
            System.out.println(c1 == c2); //true
            
            Student s = new Student();
            Class c3 = s.getClass();
            System.out.println(c2 == c3); //true
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    1.2.1定义一个类:

    package Reflect;
    
    public class Test1Class {
        private String name;
        private int age;
    
        private Test1Class() {
        }
    
        public Test1Class(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
        @Override
        public String toString() {
            return "Test1Class{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    1.2.2:进行测试

    package Reflect;
    
    import org.junit.Test;
    
    import java.lang.reflect.Constructor;
    
    public class Test1 {
        @Test
        public void testget(){
            Class c=Test1Class.class;
            Constructor[] constructor=c.getDeclaredConstructors();
            for (Constructor constructor1 : constructor) {
                System.out.println(constructor1.getName()+" "+constructor1.getParameterCount());
            }
        }
        @Test
        public void testget2() throws Exception {
            Class c2=Test1Class.class;
            Constructor constructor2=c2.getDeclaredConstructor();
            constructor2.setAccessible(true);
            Test1Class test= (Test1Class) constructor2.newInstance();
            System.out.println(test);
            System.out.println(constructor2.getName()+":"+constructor2.getParameterCount());
            Constructor constructor3= c2.getConstructor(String.class,int.class);
         System.out.println(constructor3.getName()+":"+constructor3.getName());
    
        }
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    2注解

    2.1Java注解是代码中的特殊标记,比如@Override、@Test等,作用是:让其他程序根据注解信息决定怎么执行该程序

    2.2定义注解

    public @interface MyTest2{
        String value(); //特殊属性
        int age() default 10;
    }
    
    • 1
    • 2
    • 3
    • 4

    1.MyTest1注解本质上是接口,每一个注解接口都继承子Annotation接口
    2.MyTest1注解中的属性本质上是抽象方法
    3.@MyTest1实际上是作为MyTest接口的实现类对象
    4.@MyTest1(aaa=“孙悟空”,bbb=false,ccc={“Python”,“前端”,“Java”})里面的属性值,可以通过调用aaa()、bbb()、ccc()方法获取到。

    2.3元注解:

     元注解是修饰注解的注解
    
    • 1

    @Target注解和@Retention注解:

    @Target是用来声明注解只能用在那些位置,比如:类上、方法上、成员变量上等
    @Retetion是用来声明注解保留周期,比如:源代码时期、字节码时期、运行时期
    
    • 1
    • 2

    2.4注解的解析:

    我们把获取类上、方法上、变量上等位置注解及注解属性值的过程称为解析注解。

    1.如果注解在类上,先获取类的字节码对象,再获取类上的注解
    2.如果注解在方法上,先获取方法对象,再获取方法上的注解
    3.如果注解在成员变量上,先获取成员变量对象,再获取变量上的注解
    总之:注解在谁身上,就先获取谁,再用谁获取谁身上的注解
    
    • 1
    • 2
    • 3
    • 4

    2.5注解的应用:

    可以实现有@MyTest注解的方法可以被框架执行,没有@MyTest注解的方法不能被框架执行。
    
    • 1

    3代理

    假设现在有一个大明星叫杨超越,它有唱歌和跳舞的本领,作为大明星是要用唱歌和跳舞来赚钱的,但是每次做节目,唱歌的时候要准备话筒、收钱,再唱歌;跳舞的时候也要准备场地、收钱、再唱歌。杨超越越觉得我擅长的做的事情是唱歌,和跳舞,但是每次唱歌和跳舞之前或者之后都要做一些繁琐的事情,有点烦。于是杨超越就找个一个经济公司,请了一个代理人,代理杨超越处理这些事情,如果有人想请杨超越演出,直接找代理人就可以了。
    动态代理应用举例:

    /**
     *  用户业务接口
     */
    public interface UserService {
        // 登录功能
        void login(String loginName,String passWord) throws Exception;
        // 删除用户
        void deleteUsers() throws Exception;
        // 查询用户,返回数组的形式。
        String[] selectUsers() throws Exception;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    /**
     * 用户业务实现类(面向接口编程)
     */
    public class UserServiceImpl implements UserService{
        @Override
        public void login(String loginName, String passWord) throws Exception {
            if("admin".equals(loginName) && "123456".equals(passWord)){
                System.out.println("您登录成功,欢迎光临本系统~");
            }else {
                System.out.println("您登录失败,用户名或密码错误~");
            }
            Thread.sleep(1000);
        }
    
        @Override
        public void deleteUsers() throws Exception{
            System.out.println("成功删除了1万个用户~");
            Thread.sleep(1500);
        }
    
        @Override
        public String[] selectUsers() throws Exception{
    
            System.out.println("查询出了3个用户");
            String[] names = {"张全蛋", "李二狗", "牛爱花"};
            Thread.sleep(500);
    
            return names;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    然后为UserService生成一个动态代理对象,在动态代理中调用目标方法,在调用目标方法之前和之后记录毫秒值,并计算方法运行的时间。代码如下

    public class ProxyUtil {
        public static UserService createProxy(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)/ 1000.0 + "s");
                        return rs;
                   }else {
                        Object rs = method.invoke(userService, args);
                        return rs;                                                                }
               }                                                                 });
            //返回代理对象
            return userServiceProxy;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30

    在测试类中为UserService创建代理对象

    public class Test {
        public static void main(String[] args) throws Exception{
            // 1、创建用户业务对象。
            UserService userService = ProxyUtil.createProxy(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("----------------------------------");
    
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
  • 相关阅读:
    【从头构筑C#知识体系】0.1 背景故事
    嵌入式分享合集113
    python经典百题之求奇数个数
    Eclipse配置Maven详细教程
    问:问卷中的多选题数据怎么整理?
    使用xmlrpc连接操作odoo
    快鲸scrm:轻松解决企业获客难、获客成本高等问题
    奇舞周刊第 505 期:实践指南-前端性能提升 270%!
    ubuntu静态ip地址设置
    STM32 CAN总线通讯
  • 原文地址:https://blog.csdn.net/m0_57682986/article/details/134332778