spring 反射,BigDecimal,自定义注解的使用(aop)

反射

利用反射调用它类中的属性和方法时,无视修饰符。
获取Class类的对象(三种方式)

  • Class.forName(“全类名”) (推荐使用)
  • 类名.class
  • 对象.getClass()
反射获取构造方法
	Constructor<?>[] getConstructors():返回所有公共构造方法对象的数组
	Constructor<?>[] getDeclaredConstructors():返回所有构造方法对象的数组
	Constructor<T> getConstructor(Class<?>... parameterTypes):返回单个公共构造方法对象
	Constructor<T> getDeclaredConstructor(Class<?>... parameterTypes):返回单个构造方法对象
Constructor类中用于创建对象的方法
	T newInstance(Object... initargs):根据指定的构造方法创建对象
	setAccessible(boolean flag):设置为true,表示取消访问检查,针对访问私有
反射小结
	获取class对象
		三种方式: Class.forName(“全类名”), 类名.class, 对象名.getClass()
	获取里面的构造方法对象
		getConstructor (Class<?>... parameterTypes)
		getDeclaredConstructor (Class<?>... parameterTypes)
	如果是public的,直接创建对象
		newInstance(Object... initargs)
	如果是非public的,需要临时取消检查,然后再创建对象
		setAccessible(boolean) 暴力反射
反射获取成员变量并使用
反射获取Field对象
	Field[] getFields():返回所有公共成员变量对象的数组
	Field[] getDeclaredFields():返回所有成员变量对象的数组
	Field getField(String name):返回单个公共成员变量对象
	Field getDeclaredField(String name):返回单个成员变量对象
获取成员变量并使用
* void set(Object obj,Object value) :给指定对象的成员变量赋值
* Object get(Object obj)返回指定对象的Field的值
反射获取Method对象
	Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
	Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
	Method getMethod(String name,Class<?>... parameterTypes): 返回单个公共成员方法对象
	Method getDeclaredMethod(String name,Class<?>... parameterTypes): 返回单个成员方法对象
	反射利用Method对象运行方法
	Object invoke(Object obj, Object... args):运行方法
	参数一:用obj对象调用该方法
	参数二:调用方法的传递的参数(如果没有就不写)
	返回值:方法的返回值(如果没有就不写)

新建一个实体类

package com.test.interceptor.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
 * (Student)实体类
 *
 * @author makejava
 * @since 2023-06-17 22:06:09
 */
@Data
public class Student implements Serializable {
    private static final long serialVersionUID = 533250288527593152L;
    private String sId;
    private String sName;
    private String sBirth;
    private String sSex;
    private Student(String name) {
        this.sName = name;
        System.out.println("name的值:"+name);
        System.out.println("private ... Student...有参构造方法");
    }
    public Student() {
        System.out.println("public ... Student... 无参构造方法");
    }
    public Student(String name,int age) {
        this.sName = name;
        this.sBirth = age+"";
        System.out.println("name的值:"+name +"age的值:"+age);
        System.out.println("public ... Student ... 有参构造方法");
    }
}

获取Class对象的三种方式以及通过构造方法创建对象

package com.test.interceptor.testClass;

import com.test.interceptor.domain.Student;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

/**
 * 获取class对象的三种方式
 */
public class ReflectDemo {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        // Class类中的静态方法forName(“全类名”)  全类名=包名+类名   (推荐使用)
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Student");
//        System.out.println(clazz);

        // 通过class属性来获取
        Class<Student> class2 = Student.class;
//        System.out.println(class2);

        // 通过对象的getClass()方法来获取class对象
//        Student s = new Student();
//        Class class3 = s.getClass();
//        System.out.println(class3);
        // 获取Constructor对象
        System.out.println("==================");
//        method1();
//        method2();
//        method3();
//        method4();
//        method5();
//        method6();
//        methods7();
    }

    private static void methods7() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // 获取一个私有的构造方法并创建对象
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
// 获取一个私有化的构造方法
        Constructor<?> constructor = aClass.getDeclaredConstructor(String.class);
        // 被private修饰的成员,不能直接使用的
        // 如果用反射强行获取并使用,需要临时取消访问检查
        constructor.setAccessible(true);
        // 直接创建对象
        Student student = (Student)constructor.newInstance("张三");
        System.out.println(student);
    }

    private static void method6() throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 在Class类中,有一个newInstance方法,可以利用空参直接创建一个对象
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        Student student = (Student)aClass.newInstance();
        System.out.println(student);
    }

    private static void method5() throws ClassNotFoundException, NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // Constructor类中用于创建对象的方法
        //	T newInstance(Object... initargs):根据指定的构造方法创建对象
        //	setAccessible(boolean flag):设置为true,表示取消访问检查
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        // 获取构造方法对象
        Constructor<?> constructor = aClass.getConstructor(String.class, int.class);
        Student student = (Student)constructor.newInstance("张三", 23);
        System.out.println(student);
        Constructor<?> constructor1 = aClass.getConstructor();
        Student stu = (Student) constructor1.newInstance();
        System.out.println(stu);
    }

    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        // 返回单个构造方法对象
        Constructor<?> declaredConstructor = aClass.getDeclaredConstructor(String.class);
        System.out.println(declaredConstructor);
    }

    private static void method3() throws ClassNotFoundException, NoSuchMethodException {
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        // 返回单个公共构造方法对象 ()中一定要跟构造方法的形参一致
        Constructor<?> constructor1 = aClass.getConstructor();
        System.out.println(constructor1);
        Constructor<?> constructor2 = aClass.getConstructor(String.class, int.class);
        System.out.println(constructor2);
    }

    private static void method2() throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        // 返回所有构造方法对象的数组
        Constructor<?>[] constructors = aClass.getDeclaredConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
    }

    private static void method1() throws ClassNotFoundException {
        Class<?> aClass = Class.forName("com.test.interceptor.domain.Student");
        // 返回所有公共构造方法对象的数组
        Constructor<?>[] constructors = aClass.getConstructors();
        for (Constructor<?> constructor : constructors) {
            System.out.println(constructor);
        }
    }
}

获取成员变量并使用

package com.test.interceptor.testClass;

import com.test.interceptor.domain.Stu;
import com.test.interceptor.domain.Student;

import java.lang.reflect.Field;

public class ReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
//        method1();
//        method2();
//        method3();
//        method4();

//        method5();
//        method6();
    }

    private static void method6() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Field field = clazz.getDeclaredField("address");
        // 取消访问检查,访问私有数据
        field.setAccessible(true);
        Stu student = (Stu)clazz.newInstance();
        Object o = field.get(student);
        System.out.println(o);
    }

    private static void method5() throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException {
        //        获取成员变量并使用
//* void set(Object obj,Object value) :给指定对象的成员变量赋值
//* Object get(Object obj)返回指定对象的Field的值
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Field field = clazz.getField("name");
        // 创建对象
        Stu student = (Stu) clazz.newInstance();
        // 给指定对象赋值
        field.set(student,"wangwu");
        System.out.println(student);
    }
    private static void method4() throws ClassNotFoundException, NoSuchFieldException {
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        //Field getDeclaredField(String name)返回单个成员变量对象
        Field field = clazz.getDeclaredField("address");
        System.out.println(field);
    }

    private static void method3() throws ClassNotFoundException, NoSuchFieldException {
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        // Field getField(String name)  返回单个公共成员变量对象
        // 获取成员变量必须真实存在,public修饰的
        Field name = clazz.getField("name");
        System.out.println(name);
    }
    private static void method2() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        // 返回所有成员变量对象的数组 Field[] getDeclaredFields()
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field declaredField : declaredFields) {
            System.out.println(declaredField);
        }
    }
    private static void method1() throws ClassNotFoundException {
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        // 返回所有公共成员变量对象的数组 Field[] getFields()
        Field[] fields = clazz.getFields();
        for (Field field : fields) {
            System.out.println(field);
        }
    }
}

反射获取对象的方法并使用,运行

package com.test.interceptor.testClass;

import com.test.interceptor.domain.Stu;

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

public class ReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {
//反射获取Method对象
//        method1();
//        method2();
//        method3();
//        method4();
//反射利用Method对象运行方法
//	Object invoke(Object obj, Object... args):运行方法
//	参数一:用obj对象调用该方法
//	参数二:调用方法的传递的参数(如果没有就不写)
//	返回值:方法的返回值(如果没有就不写)
        // 获取class对象
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        // 获取里面的method对象
        Method method = clazz.getMethod("function4", String.class);
        // 运行对象
        // 创建Student对象
        Stu student = (Stu)clazz.newInstance();
        Object result = method.invoke(student, "张三");
        System.out.println(result);
    }

    private static void method4() throws ClassNotFoundException, NoSuchMethodException {
        //	Method getDeclaredMethod(String name,Class... parameterTypes): 返回单个成员方法对象
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Method show = clazz.getDeclaredMethod("show");
        System.out.println(show);
        Method method = clazz.getDeclaredMethod("function2", String.class);
        System.out.println(method);
    }

    private static void method3() throws ClassNotFoundException, NoSuchMethodException {
        //	Method getMethod(String name,Class... parameterTypes): 返回单个公共成员方法对象
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Method method = clazz.getMethod("function1");
        System.out.println(method);
        Method function2 = clazz.getMethod("function2", String.class);
        System.out.println(function2);
    }

    private static void method2() throws ClassNotFoundException {
        //	Method[] getDeclaredMethods(): 返回所有成员方法对象的数组,不包括继承的
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Method[] declaredMethods = clazz.getDeclaredMethods();
        for (Method declaredMethod : declaredMethods) {
            System.out.println(declaredMethod);
        }
    }

    private static void method1() throws ClassNotFoundException {
        //	Method[] getMethods(): 返回所有公共成员方法对象的数组,包括继承的
        Class<?> clazz = Class.forName("com.test.interceptor.domain.Stu");
        Method[] methods = clazz.getMethods();
        for (Method method : methods) {
            System.out.println(method);
        }
    }
}

BigDecimal的使用(加减乘除)

BigDecimal类的构造方法:
BigDecimal(double val)    参数为double(不推荐使用)
BigDecimalString val)   参数为String(推荐使用)
public BigDecimal divide (另一个BigDecimal对象,精确几位,舍入模式) 	除法
BigDecimal小结
1BigDecimal是用来进行精确计算的
2,创建BigDecimal的对象,构造方法使用参数类型为字符串的。
3,四则运算中的除法,如果除不尽请使用divide的三个参数的方法。
代码示例:
       BigDecimal divide = bd1.divide(参与运算的对象, 小数点后精确到多少位,    舍入模式);
       参数1 ,表示参与运算的BigDecimal 对象。
       参数2 ,表示小数点后面精确到多少位
       参数3 ,舍入模式
	 BigDecimal.ROUND_UP  进一法	BigDecimal.ROUND_FLOOR 去尾法	BigDecimal.ROUND_HALF_UP 四舍五入
package com.test.interceptor.bigdecimal;

import java.math.BigDecimal;
import java.math.RoundingMode;

public class mybigdecimal {
    public static void main(String[] args) {
//        Bigdecimal的初始化时用尽量用String,假如传的是浮点类型,会丢失精度。
        // 如果想使用精确运算,那么请使用字符串的构造
//        method1();
//        methodAdd();
//        methodSubtract();
//        methodMutiply();
//        methodDivide();
//        methodDivicd1();
    }

    private static void methodDivicd1() {
// BigDecimal小结
//1, BigDecimal是用来进行精确计算的
//2,创建BigDecimal的对象,构造方法使用参数类型为字符串的。
//3,四则运算中的除法,如果除不尽请使用divide的三个参数的方法。
//代码示例:
//       BigDecimal divide = bd1.divide(参与运算的对象, 小数点后精确到多少位,    舍入模式);
//       参数1 ,表示参与运算的BigDecimal 对象。
//       参数2 ,表示小数点后面精确到多少位
//       参数3 ,舍入模式
//	 BigDecimal.ROUND_UP  进一法	BigDecimal.ROUND_FLOOR 去尾法	BigDecimal.ROUND_HALF_UP 四舍五入
        BigDecimal bd1 = new BigDecimal("0.3");
        BigDecimal bd2 = new BigDecimal("4");
        BigDecimal divide = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
        System.out.println(divide);
    }

    private static void methodDivide() {
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.3");
        BigDecimal divide = bd1.divide(bd2, 2, RoundingMode.HALF_UP);
        System.out.println(divide);
    }

    private static void methodMutiply() {
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.2");
        BigDecimal multiply = bd1.multiply(bd2);
        System.out.println("乘以为" + multiply);
    }

    private static void methodSubtract() {
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.2");
        BigDecimal subtract = bd1.subtract(bd2);
        System.out.println("差为" + subtract);
    }

    private static void methodAdd() {
        // 如果想使用精确运算,那么请使用字符串的构造
//        BigDecimal bd1 = new BigDecimal(0.1);
//        BigDecimal bd2 = new BigDecimal(0.2);
        BigDecimal bd1 = new BigDecimal("0.1");
        BigDecimal bd2 = new BigDecimal("0.2");
        BigDecimal add = bd1.add(bd2);
        System.out.println(add);
    }

    // 构造方法
    private static void method1() {
        BigDecimal bigDecimal1 = new BigDecimal(10.0);
        BigDecimal bigDecimal2 = new BigDecimal("0.3");
        System.out.println(bigDecimal1);
        System.out.println(bigDecimal2);
    }
}

自定义注解

格式: 
	public @interface 注解名称 {
        public 属性类型  属性名()default 默认值;
	}
元注解:
**@Target**	指定了注解能在哪里使用(常用)
**@Retention**	可以理解为保留时间(生命周期)(常用)
@Inherited	表示修饰的自定义注解可以被子类继承
**@Documented**	表示该自定义注解,会出现在API文档里面。(常用)

自定义一个注解(练习三)
spring 反射,BigDecimal,自定义注解的使用(aop)_第1张图片
自定义一个注解:

package com.test.interceptor.customannotation.testanno2.annotion;
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 MySysLog {
    String value() default "";
    int age() default 18;
    String[] array() default {};
}

定义一个切面类

package com.test.interceptor.customannotation.testanno2.aspect;
import com.test.interceptor.customannotation.testanno2.annotion.MySysLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

@Component
@Aspect
public class SystemLogAspect {
    @Around("@annotation(mySysLog)")
    public Object around(ProceedingJoinPoint point, MySysLog mySysLog) throws Throwable {

//        // 获取执行签名信息
//        Signature signature = point.getSignature();
//        // 通过签名获取执行操作类型(接口名)
//        String className = signature.getDeclaringTypeName();
//        // 通过签名获取执行操作类型(方法名)
//        String methodName = signature.getName();

        System.out.println(mySysLog.age());
        System.out.println(mySysLog.array()[0]);
        // class名称,方法名,参数,返回值,执行时间
        MethodSignature signature = (MethodSignature)point.getSignature();
        // 获取执行目标方法上的注解对象
        MySysLog annotation = signature.getMethod().getAnnotation(MySysLog.class);
        System.out.println(annotation.array()[0]);
        String className = point.getTarget().getClass().getName();
//        String className1 = signature.getDeclaringTypeName();
//        System.out.println(className1);
        String methodName = signature.getName();
        Object[] args = point.getArgs();
        System.out.println(className+","+methodName+","+Arrays.toString(args));
        return point.proceed();
    }
}

controller层

package com.test.interceptor.customannotation.testanno2.controller;
import com.test.interceptor.customannotation.testanno2.service.AnnotationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class AnnotationController {
    @Autowired
    private AnnotationService annotationService;

    @RequestMapping("/")
    public String testMyService() {
        annotationService.testMyService();
        return "ok...";
    }
}

service层:

package com.test.interceptor.customannotation.testanno2.service;
public interface AnnotationService {
    public void testMyService();
}

实习类:

package com.test.interceptor.customannotation.testanno2.service.impl;
import com.test.interceptor.customannotation.testanno2.annotion.MySysLog;
import com.test.interceptor.customannotation.testanno2.service.AnnotationService;
import org.springframework.stereotype.Service;
@Service
public class AnnotationServiceImpl implements AnnotationService {
    @Override
    @MySysLog(array = {"1"})
    public void testMyService() {
        System.out.println("对数据库。。。。。。");
    }
}

在启动类上加上开启aop注解

@SpringBootApplication
@EnableAspectJAutoProxy
public class InterceptorApplication {
	public static void main(String[] args) {
		SpringApplication.run(InterceptorApplication.class, args);
	}
}

加入依赖:

<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>1.9.4</version>
		</dependency>

自定义一个注解(练习一)

package com.test.interceptor.customannotation.testanno;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
// 表示Test这个注解的存活时间
@Retention(value = RetentionPolicy.RUNTIME)
public @interface anno {
}
=============================
package com.test.interceptor.customannotation.testanno;

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

public class AnnoDemo {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException {
        // 通过反射获取UseTest类的字节码文件对象
        Class<?> aClass = Class.forName("com.test.interceptor.customannotation.testanno.UseTest");
        // 创建对象
        UseTest useTest = (UseTest) aClass.newInstance();

        // 通过反射获取这个类里面所有的方法对象
        Method[] methods = aClass.getDeclaredMethods();
        // 遍历数组,得到每一个方法对象
        for (Method method : methods) {
            // method表示每一个方法的对象
            // isAnnotationPresent 判断当前方法是否有指定的注解,参数:注解的字节码文件对象,true 存在,false 不存在
            if(method.isAnnotationPresent(anno.class)) {
                method.invoke(useTest);
            }
        }
    }
}
===================================
package com.test.interceptor.customannotation.testanno;

public class UseTest {
    // 没有使用Test注解
    public void show() {
        System.out.println("UserTest... show...");
    }
    // 使用Test注解
    @anno
    public void method() {
        System.out.println("UseTest... method.....");
    }
    @anno
    public void function() {
        System.out.println("UseTest...function.....");
    }
}

练习2

package com.test.interceptor.customannotation.testanno1;
import java.lang.annotation.*;
//@Inherited // 指定该注解可以被继承
@Documented
@Retention(RetentionPolicy.RUNTIME) // 指定了该注解的存活时间
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE}) // 指定注解使用的位置(成员变量,类,方法上)
public @interface Anno {
}
==================================
package com.test.interceptor.customannotation.testanno1;
@Anno
public class Person {
}
=====================
package com.test.interceptor.customannotation.testanno1;

public class Student extends Person{
    public void show() {
        System.out.println("student...show...");
    }
}
===============
package com.test.interceptor.customannotation.testanno1;

public class StudentDemo {
    public static void main(String[] args) throws ClassNotFoundException {
        // 获取到student类的字节码文件对象
        String className = "com.test.interceptor.customannotation.testanno1.Student";
        Class<?> aClass = Class.forName(className);
        // 获取注解
        boolean result = aClass.isAnnotationPresent(Anno.class);
        System.out.println(result);
    }
}

实现注解的步骤

  1. 声明注解
  2. 添加注解
  3. 获取添加了注解的目标,通常使Class对象,Method对象,Field对象,还有Contructor对象,Parameter对象,Annotation对象等。
  • 通过已知对象,获取Class对象
  • 通过全类路径,获取Class对象
  • 扫描包路径,获取Class对象
  1. 实现注解处理器,借助反射,获取注解对象,读取注解属性值,然后根据注解及属性值做相应处理。
 // value
    public String value();

    // 定义一个基本类型的属性
    int a() default 23;
    // 定义一个String类型的属性
    public String name() default "itheima";
    // 定义一个Class类型的属性
    public Class clazz() default Anno2.class;
    // 定义一个注解类型的属性
    public Anno2 anno() default @Anno2;
    // 定义一个枚举类型的属性
    public Season season() default Season.SPRING;

    // 以上类型的一维数组
    // int 类型  枚举类型
    public int[] arr() default {1,2,3,4,5};
    public Season[] seasons() default {Season.SPRING,Season.SUMMER};

https://www.bilibili.com/read/cv13282317

你可能感兴趣的:(spring,java,jvm)