java进阶学习笔记

学习java深度学习,提升编程思维,适合掌握基础知识的工作者学习

  • 1.反射和代理
    • 1.1 概念介绍
    • 1.2应用场景
    • 1.3 反射-reflect
      • 1.3.1 获得类-Class
      • 1.3.2 获得类的字段-Field
      • 1.3.3 动态访问和修改对象实例的字段
      • 1.3.4 获得类方法-Method
      • 1.3.5 调用方法.invoke
      • 1.3.6 类实例化-构造函数Constructor
      • 1.3.7 instanceof
      • 1.3.8 利用反射来解析spring配置
    • 1.4 代理-proxy
      • 1.4.1 代理模式
      • 1.4.2 准备工作
      • 1.4.3 静态代理
    • 1.5 动态代理
      • 1.5.1 InvocationHandler介绍
      • 1.5.2 Proxy类
      • 1.5.3动态代理类的实现
      • 1.5.4动态实现接口
      • 1.5.4替换某个方法
    • 1.5 动态代理框架CGLIB
      • 1.5.1 使用介绍
      • 1.5.2 cglib说明
    • 1.6 总结
  • 2. java小干货
    • 2.1循环遍历
    • 2.2可变参数
    • 2.3 list和数组转化
    • 2.4 地址引用
    • 2.5集合
    • 2.6文件流
    • 2.7java代码块、内部类和匿名类
    • 2.8 java泛型及通配符
    • 2.9 日期类LocalDate
    • 2.10枚举
    • 2.11 java常见数据结构
  • 3. java注解
  • 4. lambda语言
  • 5.http网络
  • 6.java线程

1.反射和代理

1.1 概念介绍

在Java编程中,反射和代理是两个强大的特性,能够在运行时动态地操作和扩展类的行为。通过反射,我们可以在不知道类的具体信息的情况下操作类的属性和方法;而代理则允许我们创建一个代理类来拦截并增强目标对象的行为

1.2应用场景

像咱们平时大部分时候都是在写业务代码,很少会接触到直接使用反射机制的场景。
但是,这并不代表反射没有用。相反,正是因为反射,你才能这么轻松地使用各种框架。像 Spring/Spring Boot、MyBatis 等等框架中都大量使用了反射机制,掌握反射和代理机制,有利于我们了解这些框架的内核原理,提升编程思维

  • xml的bean配置的注入
  • AOP拦截
  • 数据库事务
  • springMVC
  • Java注解
  • 开发工具如IDEA,提供一个类的属性方法展示给我们智能快捷选择

这些内核都是反射和代理机制在其作用

1.3 反射-reflect

由于JVM为每个加载的class创建了对应的Class实例,并在实例中保存了该class的所有信息,包括类名、包名、父类、实现的接口、所有方法、字段等,因此,如果获取了某个Class实例,我们就可以通过这个Class实例获取到该实例对应的class的所有信息。这种通过Class实例获取class信息的方法称为反射(Reflection)。

我们正常得到一个对象实例是通过new方法创建对象;反射就是通过class来实现,
1.获得类class
2.获得类的字段属性和方法
3.获得类的实例对象
4.获得对方法的调用

准备工作

Food.java

public class Food {private Integer id;private  String name;// ....省略get set 等
}

1.3.1 获得类-Class

获得类有三种方式,看代码演示

类.class
对象.getClass();
Class.forName(“类名”)

 /**** @Description: 得到Class*/@Testpublic void t1() throws ClassNotFoundException {Class cls=null;//1.通过类名直接获得cls= Food.class;//2.通过实例获得cls=new Food(1, "火锅").getClass();//3.通过路径+类名的字符串获得cls=Class.forName("com.jsoft.reflection.Food");printClassInfo(cls);}/**** @Description: 读取类的信息*/static void printClassInfo(Class cls) {System.out.println("Class name: " + cls.getName());System.out.println("Simple name: " + cls.getSimpleName());if (cls.getPackage() != null) {System.out.println("Package name: " + cls.getPackage().getName());}System.out.println("is interface: " + cls.isInterface());System.out.println("is enum: " + cls.isEnum());System.out.println("is array: " + cls.isArray());System.out.println("is primitive: " + cls.isPrimitive());}

打印效果

Class name: com.jsoft.reflection.Food
Simple name: Food
Package name: com.jsoft.reflection
is interface: false
is enum: false
is array: false
is primitive: false

1.3.2 获得类的字段-Field

演示代码

public class Father  extends Man{private Integer age;public  String job;}public class Man{private Integer id;private String name;public String address;}

对任意的一个Object实例,只要我们获取了它的Class,就可以获取它的一切信息。
我们先看看如何通过Class实例获取字段信息。Class类提供了以下几个方法来获取字段:

方法说明
Field getField(name)根据字段名获取某个public的field(包括父类)
Field[] getFields()获取所有public的field(包括父类)
Field getDeclaredField(name)根据字段名获取当前类的某个field(不包括父类)
Field[] getDeclaredFields():获取当前类的所有field(不包括父类)

注意:
Declared修饰就只管当前类字段,和private、public无关
否则就包含父类的public

测试代码

 @Testpublic void t2() throws NoSuchFieldException {Class cls= Father.class;//1.得到当前类的所有字段,不包含父类Field[] fs=cls.getDeclaredFields();System.out.println("1.得到当前类的所有字段,不包含父类");for (Field f : fs) {printFeild(f);}//2.得到当前类某个字段System.out.println("2.得到当前类某个字段,不包含父类");Field f=cls.getDeclaredField("job");printFeild(f);//3.得到当前类及父类的所有public字段System.out.println("3.得到当前类及父类的所有public字段");fs=cls.getFields();for (Field f1 : fs) {printFeild(f);}//4.得到当前类及父类的public字段System.out.println("4.得到当前类及父类的public字段,如果是private,则要报错");f=cls.getField("address");printFeild(f);}/**** @Description: 打印字段信息*/public  void printFeild(  Field f){System.out.println("//------------字段信息 start");System.out.println("字段名称:"+f.getName());System.out.println("字段类型:"+f.getType().getName());int m = f.getModifiers();System.out.println("field is final:"+Modifier.isFinal(m));; // trueSystem.out.println("field is Public:"+Modifier.isPublic(m));; // trueSystem.out.println("field is Protected:"+Modifier.isProtected(m));; // trueSystem.out.println("field is Private:"+Modifier.isPrivate(m));; // trueSystem.out.println("field is Static:"+Modifier.isStatic(m));; // trueSystem.out.println("//------------字段信息 end");}

1.3.3 动态访问和修改对象实例的字段

我们可以通过一个对象对应的class去动态访问或修改对象的字段
Field.set(vo对象,修改值) //修改字段值
Feild.get(vo对象) //获得字段值
Feild.setAccessible(true); //私有字段,需要设置这个允许访问,否则报异常

  @Testpublic void t3() throws NoSuchFieldException, IllegalAccessException {Food food=new Food(1, "火锅");System.out.println("food.getName:"+food.getName());Class cls=food.getClass();Field f=cls.getDeclaredField("name");f.setAccessible(true); //不设置这个private 字段要抛出异常//通过field获得值Object name= f.get(food);System.out.println("name:"+name);//通过field设置值f.set(food, "西北风");System.out.println("name:"+food.getName());}

1.3.4 获得类方法-Method

方法说明
Method getMethod(name, Class…)获取某个public的Method(包括父类)
Method[] getMethods()获取所有public的Method(包括父类)
Method getDeclaredMethod(name, Class…)获取当前类的某个Method(不包括父类)
Method[] getDeclaredMethods():获取当前类的所有Method(不包括父类)

示例代码

@Data
public class Father  extends Man{private Integer age;public  String job;public  String play(int type){System.out.println("param value:"+type);return type+"";}public  String sleep(String type, Date date){System.out.println("param value type:"+type+";date:"+date);return type+"";}private  void self(){System.out.println("this is private method");}public void dd(){System.out.println("没有参数方法()");}}@Data
public class Man{private Integer id;private String name;public String address;@Overridepublic Food eat() {return new Food(1,"火锅");}
}

测试代码

@Testpublic void t4() throws IllegalAccessException, NoSuchMethodException {Class cls= Father.class;System.out.println("1. 获取所有public的Method(包括父类)");Method[] methods=cls.getMethods();for (Method method : methods) {printMethod(method);}System.out.println("2. 获取某个public的Method(包括父类)");//第一个参数为方法名,第二参数是可变参数,传递方法的参数类型,如果无参数则不传递Method m= cls.getMethod("getName");printMethod(m);//方法有1个参数//注意int foat double这些基本类型对用的类是int.class,不是Integer.classm=cls.getMethod("play", int.class);printMethod(m);//方法有多个参数m=cls.getMethod("sleep", String.class, Date.class);printMethod(m);System.out.println("3. 获取当前类的的Method(不包括父类)");m= cls.getDeclaredMethod("getJob");printMethod(m);//私有方法也可以m= cls.getDeclaredMethod("self");//父类方法不可以,要报java.lang.NoSuchMethodExceptionm= cls.getDeclaredMethod("eat");printMethod(m);printMethod(m);}public void printMethod(Method addMethod){System.out.println("---------方法名称: 【" + addMethod.getName()+"】---相关属性------------");System.out.println("修饰符: " + Modifier.toString(addMethod.getModifiers())); //public private等System.out.println("返回值: " + addMethod.getReturnType()); //返回值类型的class数组Class[] paramsCls= addMethod.getParameterTypes(); //参数值类型对应的class数组}

1.3.5 调用方法.invoke

我们可以用Method.invoke(vo,参数)来调用方法

代码

@Testpublic void t5() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {Father father=new Father();Class cls= father.getClass();Method m=null;//无参无返回方法m=cls.getMethod("dd");m.invoke(father);//有参数,有返回值m=cls.getMethod("sleep", String.class,Date.class);String ret=(String)m.invoke(father, "1",new Date());System.out.println("返回值:"+ret);//private方法调用m=cls.getDeclaredMethod("self");//私有方法必须设置为m.setAccessible(true);m.setAccessible(true);m.invoke(father);}

jdk内置对象的方法调用的另外一种写法

  @Testpublic void t6() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {String s="abcde";String sub=s.substring(0,2);System.out.println(sub);//通过类加载Class   cls=String.class;Method method=cls.getMethod("substring",int.class,int.class);sub=(String) method.invoke(s, 0,2);System.out.println(sub);}

Method m =Father.class.getMethod(“dd”);
m.invoke(new Father());

其实就相当于

Father f=new Father();
f.dd();

1.3.6 类实例化-构造函数Constructor

实例化对象有3中方法
1.我们都知道的new 对象Father father=new Father();
2.通过类class:newInstance
3.构造方法:Constructor

准备类

public class Const {private Integer id;private String name;public Const() {System.out.println("无参数构造方法");}public Const(Integer id, String name) {System.out.println("有参数构造方法");this.id = id;this.name = name;}
}

在很多框架里,我们为了足够的扩展,都通过配置来实现类的实例化

Class.newInstance()

  @Testpublic void t7() throws ClassNotFoundException, InstantiationException, IllegalAccessException {Class cls =Class.forName("com.jsoft.reflection.Const");Const aConst = (Const) cls.newInstance();}

Class.newInstance()最大的问题是只能实例化无参的构造方法,如果我们把无参构造方法屏蔽掉,代码会出错,所以我们需要使用Constructor类来实现有参的构造方法

这里是引用一共有4种方法,全部都在Class类中:

  1. getConstructors():获取类中的公共方法
  2. getConstructor(Class[] params): 获取类的特定构造方法,params参数指定构造方法的参数类型
  3. getDeclaredConstructors(): 获取类中所有的构造方法(public、protected、default、private)
  4. getDeclaredConstructor(Class[] params): 获取类的特定构造方法,params参数指定构造方法的参数类型

代码示例

    @Testpublic void t8() throws ClassNotFoundException, InstantiationException, IllegalAccessException, NoSuchMethodException, InvocationTargetException {Class cls =Class.forName("com.jsoft.reflection.Const");//得到所有构造函数Constructor[] constructors=  cls.getConstructors();for (Constructor constructor : constructors) {System.out.println("修饰符: " + Modifier.toString(constructor.getModifiers()));System.out.println("构造函数名: " + constructor.getName());System.out.println("参数列表: " );Class[] cs= constructor.getParameterTypes();for (Class c : cs) {System.out.println(c.getName());}}//获得具体一个(无参)Constructor cst=cls.getConstructor();//newInstance实例化Const const1=(Const) cst.newInstance();//获得具体一个(有参)cst=cls.getConstructor(Integer.class,String.class);//传入构造函数的参数的类型//newInstance实例化const1=(Const) cst.newInstance(1,"蒋增奎");}

1.3.7 instanceof

instanceof是判断一个实例对象是不是一个类的实例,是则返回true
对象 instanceof 类

class Person{
}class Teacher extends Person{
}class Student extends Person{
}

测试

public class test01 {public static void main(String[] args) {Object obj = new Student(); // 主要看这个对象是什么类型与实例化的类名System.out.println(obj instanceof Student); // trueSystem.out.println(obj instanceof Person); // trueSystem.out.println(obj instanceof Object); // trueSystem.out.println(obj instanceof String); // falseSystem.out.println(obj instanceof Teacher); // false  无关系System.out.println("========================");Person person = new Student();System.out.println(person instanceof Person); // trueSystem.out.println(person instanceof Object); // true// System.out.println(person instanceof String); // 编译错误System.out.println(person instanceof Teacher); // false 无关系}
}

1.3.8 利用反射来解析spring配置

<bean id="employee" class="com.jsoft.po.Employee"><property name="id" value="1" /><property name="name" value="蒋增奎" /><property name="deptId" value="001" />
</bean>

解析思路

1.用dom4j解析xml得到xml数据
2.创建类:Class cls=Class.forName(“Employee”);
3.创建对象:Employee obj=(Employee)cls.newInstance();
4.调用修改字段或者方法给字段注入值

1.4 代理-proxy

1.4.1 代理模式

代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。

代理模式作用:
代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法执行前后你可以增加一>些自定义的操作。

代理模式价值
代理模式的价值在于不修改代理类代码,增加其他功能,我们理解成我们通常所说的赋能
(1)比如日常生活中的品牌加盟,我们忽悠一个饭店加盟一个品牌连锁,我们忽悠饭店,你只需要开店,营销、菜品、供应链我们全部帮你搞定。
(2)比如老板要求我们所有方法都要加入日志,优雅的方法,不是修改以前代码,而是增加一个代理,把在代理类去处理日志,这就是spring框架的日志、事务原理

举个例子:
boy向girl求婚
(1)现代:boy和girl直接发生通信,girl迫不及待的同意了
(2)古代:boy不能直接和girl发生关系,需要通过媒婆,boy向媒婆发起请求,媒婆转告girl,gilr同意,媒婆觉得女孩如果同意,婚前应该收彩礼10万,婚后不能家暴,媒婆就是代理,在原始的反馈上增加了自己的要求,提升了框架的健壮性。
在这里插入图片描述
代理分为静态代理和动态代理两种类型

1.4.2 准备工作

public interface Love {/**** @Description: 结婚请求*/public void marray();/**** @Description: 睡觉请求*/public void sleep();public String like(int type);public int saveMoney(int money);
}/**
接口实现类
**/
public class LoveImpl implements Love {@Overridepublic void marray() {System.out.println("我同意");}public void sleep() {System.out.println("我同意");}public String like(int type){if(type==1)return "69";return "96";}@Overridepublic int saveMoney(int money) {return money*10;}
}

1.4.3 静态代理

静态代理实现步骤:
1.定义一个接口及其实现类;
2.创建一个代理类同样实现这个接口
3.将目标对象注入进代理类,然后在代理类的对应方法调用目标类中的对应方法。这样的话,我们就可以通过代理类屏蔽对目标对象的访问,并且可以在目标方法执行前后做一些自己想做的事情。

代码:

//代理类要实现接口
public class LoveProxy implements Love {private Love target;//代理的接口/**** @Description: 构造方法注入代理的接口*/public LoveProxy(Love love){target=love;}@Overridepublic void marray(){System.out.println("============代理marray方法");System.out.println("要彩礼10万");target.marray();System.out.println("不能家暴");}public void sleep(){System.out.println("============代理sleep方法");System.out.println("安全措施");target.sleep();}public String like(int type){System.out.println("============代理like方法");System.out.println("注意身体");return target.like(type);}public static void main(String[] args) {//实际应用:代理的应用Love love=new LoveImpl();LoveProxy proxy=new LoveProxy(love);proxy.marray();proxy.sleep();System.out.println( proxy.like(1));}}

效果:在以前的需求上扩展了功能

============代理marray方法
要彩礼10万
我同意
不能家暴
============代理sleep方法
安全措施
我同意
============代理like方法
注意身体
69

总结:代理模式的实现

1.给一个要代理的类升级一个接口
2.代理目标类和代理类都实现这个接口
3.把目标类传入代理类。代理类是方法里面去封装目标类的实现

1.5 动态代理

静态代理:通过手动编写代理类来实现,需要为每个目标对象编写一个代理类。
动态代理:通过Java提供的相关接口和类,在运行时动态生成代理类,无需手动编写代理类。

我们仍然先定义了接口,但是我们并不去编写实现类,而是直接通过JDK提供的一个Proxy.newProxyInstance()创建了一个Hello接口对象。这种没有实现类但是在运行期动态创建了一个接口对象的方式,我们称为动态代码。JDK提供的动态创建接口对象的方式,就叫动态代理。

动态代理三个重要的java类

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

1.5.1 InvocationHandler介绍

代理实例的调用处理器需要实现InvocationHandler接口,并且每个代理实例都有一个关联的调用处理器。当一个方法在代理实例上被调用时,这个方法调用将被编码并分派到其调用处理器的invoke方法上。
接口里最重要的方法invoke

  public Object invoke(Object proxy, Method method, Object[] args)throws Throwable;

其有三个参数,分别为:
proxy:是调用该方法的代理实例,是java在编译环节自动生成的,对开发者没有意义,如:jdk.proxy1.$Proxy0,注意不是代理的目标类,也不是接口。

method:是在代理实例上调用的接口方法对应的Method实例。

args:一个对象数组,其中包含在代理实例上的方法调用中传递的参数值,如果接口方法不带任何参数,则为 null。基元类型的参数包装在相应基元包装类的实例中,例如 java.lang.Integer 或 java.lang.Boolean

返回值:调用代理实例上的方法的返回值。
如果接口方法声明的返回类型是基元类型,那么该方法返回的值必须是对应基元包装类的实例;
否则,它必须是可分配给声明的返回类型的类型。如果此方法返回的值为 null,并且接口方法的返回类型为基元,则代理实例上的方法调用将引发 NullPointerException。如果此方法返回的值与接口方法的声明返回类型不兼容(如上所述),则代理实例上的方法调用将引发 ClassCastException

这里最重要的参数是method,可以通过moth.invote调用目标对象的方法

1.5.2 Proxy类

Proxy类提供了创建动态代理类及其实例的静态方法,该类也是动态代理类的超类,其最主要的方法是一个newProxyInstance的静态方法

   public static Object newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h){......}

参数说明:
ClassLoader :
对应代理目标类对应的类加载器
Class<?>[] interfaces
目标代理类的接口类对应的CLASS,代理目标类的接口可以是多个
InvocationHandler h
要调用的处理器
返回对象:
返回实例,Object可以转化成对应的目标代理类的接口

1.5.3动态代理类的实现

准备代码:为了增加效果,我们在增加一个类和接口

public interface LifeService {public String eat(String name);public String drink(String name);public int like(int type);}public class Life implements LifeService {public String eat(String name){String ret="I like eat:"+name;System.out.println(ret);return ret;}public String drink(String name){String ret="I like drink:"+name;System.out.println(ret);return ret;}public int like(int type){String ret="mylike:"+type;System.out.println(ret);return type;}}

自己做一个调度类,继承InvocationHandler

//自己编写处理器
public class MyHandler implements InvocationHandler {private  Object target;//代理的目标类//通过构造方法注入代理的目标public MyHandler(Object target){this.target=target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//给所有方法加上日志System.out.println("给大家增加一个log日志...........");String mName=method.getName();//给以save开头的方法名添加事务if(mName.length()>=4 && "save".equals(mName.substring(0,4))){System.out.println("开启事务...............");}//方法名是sleep的增加安全措施if("sleep".equals(mName)){System.out.println("注意安全措施...............");}//调用目标代理类的方法并返回方法返回值return method.invoke(target,args);}}

封装一个调度工厂

public class ProxyFactory {/**** @Description: 动态代理工厂* @Create:2023/12/24 12:43* @Param: [target:代理的对象实例* @Return: java.lang.Object  代理接口对象*/public static Object creatProxy(Object target){//动态调用代理return  Proxy.newProxyInstance(target.getClass().getClassLoader(),  //目标的加载target.getClass().getInterfaces(), //目标类的接口的class,可以是多个,数组,如果指定,则要使用new Class[...]new MyHandler(target));}public static void main(String[] args) {//应用1Love love=(Love)creatProxy(new LoveImpl() );love.marray();love.sleep();int money=love.saveMoney(10);System.out.println("存钱:"+money);//应用2LifeService lifeService=(LifeService)creatProxy(new Life());lifeService.eat("火锅");lifeService.drink("可乐");}
}

执行效果:

给大家增加一个log日志...........
我同意
给大家增加一个log日志...........
注意安全措施...............
我同意
给大家增加一个log日志...........
开启事务...............
存钱:100
给大家增加一个log日志...........
I like eat:火锅
给大家增加一个log日志...........
I like drink:可乐

1.5.4动态实现接口

有时候,我们不想为接口单独做一个实现类,我们可以通过动态代理来实现,这个在springboot里面非常常见的编程思想

public class DynamicProxy {public static void main(String[] args) {//定义一个InvocationHandler对象,但不传入实现类,相当于InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if (method.getName().equals("marray")) { //这个方法去实现,和做一个实现类原理一致System.out.println("我同意个锤子");}return null;}};Love love = (Love) Proxy.newProxyInstance(Love.class.getClassLoader(), // 传入ClassLoadernew Class[] { Love.class }, // 传入要实现的接口handler); // 传入处理调用方法的InvocationHandlerSystem.out.println("3333");love.marray();}
}

1.5.4替换某个方法

在大量的java框架中,某种功能有默认实现,我们想替换掉,自己定义实现,其他方法不变,我们也可以使用动态代理技术实现。

public class ProxyReplcae {public static void main(String[] args) {LoveImpl loveImp=new LoveImpl();//默认实现,在spring里一般采用注入//定义一个InvocationHandler对象InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//这个对象不想使用以前实现,自定义实现if (method.getName().equals("marray")) {System.out.println("不同意结婚");return null;}elsereturn method.invoke(loveImp,args); //其他的依然使用默认实现}};Love love = (Love) Proxy.newProxyInstance(Love.class.getClassLoader(), // 传入ClassLoadernew Class[] { Love.class }, // 传入要实现的接口handler); // 传入处理调用方法的InvocationHandlerlove.marray();  //已经使用自定义love.sleep();//依然是默认实现}}

1.5 动态代理框架CGLIB

JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类。
为了解决这个问题,我们可以用 CGLIB 动态代理机制来避免。

CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB 通过继承方式实现代理。很多知名的开源框架都使用到了CGLIB, 例如 Spring 中的 AOP 模块中:如果目标对象实现了接口,则默认采用 JDK 动态代理,否则采用 CGLIB 动态代理。

1.5.1 使用介绍

1.引入框架

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>

2.准备好一个普通类

public class MyDay {public void work(int hour){System.out.println(hour+"点开始工作");}public void sleep(int hour){System.out.println(hour+"点开始睡觉");}
}

代码


import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;/*** @class: com.jsoft.reflection.CglibProxyFacory* @description:* @author: jiangzengkui* @company: 教育家* @create: 2023-12-24 15:29*/
public class CglibProxyFacory {/***clazz:代理目标类的class*/public static Object getProxy(Class<?> clazz) {//自定义一个拦截器MethodInterceptor me=new MethodInterceptor(){/*** @param o           被代理的对象(需要增强的对象)* @param method      被拦截的方法(需要增强的方法)* @param args        方法入参* @param methodProxy 用于调用原始方法*/@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy)throws Throwable {System.out.println("before method " + method.getName());Object object = methodProxy.invokeSuper(o, args);//调用方法之后,我们同样可以添加自己的操作System.out.println("after method " + method.getName());return object; // 方法的返回值,如果void则为null}};// 创建动态代理增强类Enhancer enhancer = new Enhancer();// 设置类加载器enhancer.setClassLoader(clazz.getClassLoader());// 设置被代理类enhancer.setSuperclass(clazz);// 设置方法拦截器enhancer.setCallback(me);// 创建代理类return enhancer.create();}public static void main(String[] args) {MyDay myDay= (MyDay) CglibProxyFacory.getProxy(MyDay.class);myDay.work("早上8");myDay.sleep("晚上23");}}

效果:

before method work
早上8点开始工作
after method work
before method sleep
晚上23点开始睡觉
after method sleep

1.5.2 cglib说明

主要要用到的3个类

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

net.sf.cglib.proxy.MethodInterceptor

这个就是拦截器处理接口,其重要接口方法

/*** @param obj           被代理的对象(需要增强的对象)* @param method      被拦截的方法(需要增强的方法)* @param args        方法入参* @param proxy 用于调用原始方法* renturn  方法的返回值,如果void则为null*/public Object intercept(Object obj, java.lang.reflect.Method method,Object[] args,MethodProxy proxy) throws Throwable;

net.sf.cglib.proxy.MethodProxy

这个方法为调用代理目标类的原始方法,其调用函数:MethodProxy.invokeSuperr(Object obj, Object[] args) ,其自动为代理目标类创建一个接口

/**
Object obj:传入代理目标类对象实例Object[] args:代理目标类的方法参数**/
public Object invokeSuper(Object obj, Object[] args) throws Throwable {try {init();FastClassInfo fci = fastClassInfo;return fci.f2.invoke(fci.i2, obj, args);} catch (InvocationTargetException e) {throw e.getTargetException();}}

net.sf.cglib.proxy.Enhancer

这个类用于调用拦截器,创建增强的代理目标类

 		// 创建动态代理增强类Enhancer enhancer = new Enhancer();// 设置类加载器enhancer.setClassLoader(clazz.getClassLoader());// 设置被代理类enhancer.setSuperclass(clazz);// 设置方法拦截器enhancer.setCallback(me);// 创建代理类-增强后的目标代理类Object obj=enhancer.create();

1.6 总结

反射机制:

  • 根据类的名称或者class本身,可以进行实例化对象、构造方法、获得和修改字段、获得方法名和调用方法

代理机制:

  • 代理机制就是代理本身目标类,增强其功能
  • 静态代理,就是继承目标类对应的接口,实现所有的接口方法,通过接口的封装,增强目标类
  • 动态代理:就是创造一个拦截器,拦截器里去增强目标类的方法,前提:必须有接口类
  • Cglib:增对目标类没有接口这种情况,自动创建一个接口,实现没有接口类也可以做代理

2. java小干货

2.1循环遍历

2.2可变参数

2.3 list和数组转化

2.4 地址引用

2.5集合

2.6文件流

2.7java代码块、内部类和匿名类

2.8 java泛型及通配符

2.9 日期类LocalDate

2.10枚举

2.11 java常见数据结构

3. java注解

4. lambda语言

5.http网络

6.java线程

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/225455.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Playbook 角色的使用

本章主要介绍ansible 中角色的使用。 了解什么是角色 独立地写一个角色 使用角色 系统自带角色的使用 ansible Galaxy的使用 目录 1. 了解角色 2. 手把手创建角色 3. 使用角色 4.系统自带的角色 5. 修改端口上下文 6. 使用Ansible Galaxy 1. 了解角色 正常情况下,配…

关于增强监控以检测针对Outlook Online APT活动的动态情报

一、基本内容 2023年6月&#xff0c;联邦民事行政部门&#xff08;FCEB&#xff09;在其Microsoft 365&#xff08;M365&#xff09;云环境中发现了可疑活动。该机构迅速向Microsoft和网络安全和基础设施安全局&#xff08;CISA&#xff09;报告了此情况。经过深入调查&#x…

WPS中如何根据身份证号生成出生日期并排序

1. wps中如何根据身份证号导出出生日期并排序 1.1 wps中建一张表 1.2 使用转日期格式导出出生日期 DATE(VALUE(MID(C2,7,4)),VALUE(MID(C2,11,2)),VALUE(MID(C2,13,2)))MID(C2, 7, 4)&#xff1a;这部分从单元格 C2 中提取文本字符串&#xff0c;从第7个字符开始提取长度为4的…

Seem环境安装

创建虚拟环境 conda create -n seem python3.8 conda activate seem 安装相关依赖&#xff1a;&#xff08;不按照的话会报错&#xff09; sudo apt-get install openmpi-bin libopenmpi-devconda install gcc_linux-64pip install mpi4py 导入环境 export PYTHONPATH$(pwd…

使用CRA(create-react-app)初始化一个完整的项目环境(该初始化项目已上传到本文章的资源)

1. 整理项目结构&#xff0c;项目目录结构大致划分如下&#xff1a; 2. 安装sass 安装sass开发环境, 注意&#xff1a;使用的文件后缀名要用.scssnpm i sass -D3. 安装Ant Design npm i antd --save 4. 配置基础路由Router&#xff08;具体可参考ReactRouter使用详解&#x…

[PyTorch][chapter 8][李宏毅深度学习][DNN 训练技巧]

前言&#xff1a; DNN 是神经网络的里面基础核心模型之一.这里面结合DNN 介绍一下如何解决 深度学习里面过拟合,欠拟合问题 目录&#xff1a; DNN 训练常见问题 过拟合处理 欠拟合处理 keras 项目 一 DNN 训练常见问题 我们在深度学习网络训练的时候经常会遇到下面…

Visual Studio2022配置ReSharper C++ 常用设置

如需安装免费的可以在下面留言&#xff0c;看到即回复 文章目录 Visual Studio2022配置ReSharper C 常用设置配置Visual Studio2022&#xff0c;使其能够按回车进行补全配置ReSharper C 设置自动弹出配置ReSharper C 的快捷键ReSharper C 去掉注释拼写使用中文注释 如何关闭新版…

ansible 备忘清单(一)

笔者&#xff1a; 把以前的手写笔记电子化吧&#xff0c;顺便当作复习。 基础命令 命令 参数 备注 ansible --version 查看版本号 ansible-doc --help 查看帮助信息 -l &#xff5c;--list 查看所有模块 -s 查看模块摘要 Ansible servers -I &#xff5c;-…

test-03-java 单元测试框架 testNG 入门介绍 junit/junit5/testNG 详细对比

拓展阅读 test-01-java 单元测试框架 junit 入门介绍 test-02-java 单元测试框架 junit5 入门介绍 test-03-java 单元测试框架 testNG 入门介绍 junit/junit5/testNG 详细对比 test assert-01-Google Truth 断言 test 系统学习-03-TestNG Spock testng 入门使用教程 开源…

【Vue篇】基础篇—Vue指令,Vue生命周期

&#x1f38a;专栏【JavaSE】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f384;欢迎并且感谢大家指出小吉的问题&#x1f970; 文章目录 &#x1f354;Vue概述&#x1f384;快速入门&#x1f33a;Vue指令⭐v-…

Android studio 连接夜神模拟器

前言&#xff1a; 在夜神模拟器安装目录&#xff0c;直接打开powerShell&#xff0c;然后输入&#xff1a;nox_adb.exe connect 127.0.0.1:62001&#xff0c;命令无法执行出现以下错误&#xff1a; 按照上面的提示&#xff0c;键入&#xff1a;.\nox_adb.exe 依然无法执行 如…

layui表格中预览视频和图片

全代码 <!DOCTYPE html> <html><head><title>Layui&#xff1a;数据表格table中预览图片、视频</title><meta charset"utf-8"/><link rel"stylesheet" href"../dist/css/layui.css"><style>&l…

模式识别与机器学习-判别式分类器

模式识别与机器学习-判别式分类器 生成式模型和判别式模型的区别线性判别函数多分类情况多分类情况1多分类情况2多分类情况3 例题 广义线性判别函数实例 分段线性判别函数Fisher线性判别感知机算法例&#xff1a;感知机多类别分类 谨以此博客作为学习期间的记录 生成式模型和判…

D9741 PWM控制器电路,定时闩锁、短路保护电路,输出基准电压(2.5V) 采用SOP16封装

D9741是一块脉宽调制方三用于也收路像机和笔记本电的等设备上的直流转换器。在便携式的仪器设备上。 主要特点&#xff1a;● 高精度基准电路 ● 定时闩锁、短路保护电路 ● 低电压输入时误操作保护电路 ● 输出基准电…

智能优化算法应用:基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于骑手优化算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.骑手优化算法4.实验参数设定5.算法结果6.…

【WPF】使用Behavior以及ValidationRule实现表单校验

文章目录 使用ValidationRule实现检测用户输入EmptyValidationRule 非空校验TextBox设置非空校验TextBox设置非空校验并显示校验提示 结语 使用ValidationRule实现检测用户输入 EmptyValidationRule是TextBox内容是否为空校验&#xff0c;TextBox的Binding属性设置ValidationRu…

使用 Elasticsearch 检测抄袭 (二)

我在在之前的文章 “使用 Elasticsearch 检测抄袭 &#xff08;一&#xff09;” 介绍了如何检文章抄袭。这个在许多的实际使用中非常有意义。我在 CSDN 上的文章也经常被人引用或者抄袭。有的人甚至也不用指明出处。这对文章的作者来说是很不公平的。文章介绍的内容针对很多的…

解决Pycharm pip安装模块太慢问题,pycharm2022没有manage repositories配置镜像源

解决方案 方法清华阿里云中国科技大学华中理工大学 或者直接-i 加镜像 方法 URL写下面任意一个 清华 https://pypi.tuna.tsinghua.edu.cn/simple阿里云 http://mirrors.aliyun.com/pypi/simple/中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/华中理工大学 http:/…

前端项目重构的深度思考和复盘

摘要&#xff1a; 项目重构是每一家稳定发展的互联企业的必经之路, 就像一个产品的诞生, 会经历产品试错和产品迭代 一样, 随着业务或新技术的不断发展, 已有架构已无法满足更多业务扩展的需求, 所以只有通过重构来让产品“进化”, 才能跟上飞速发展的时代浪潮. 技术因素 早期…

TVS 管选型与 ESD 防护设计

文章目录 ESD 防护设计 TVS管的基础特性 TVS管的选型方法 TVS管布局细节 参考文献 ESD 防护设计 静电防护设计是让电路板外接的各类金属按钮开关在接触到外界空气放电或接触放电时&#xff0c;在这种瞬间出现的大能量注入到电路板后&#xff0c;能够通过某种设计好的通道泄…