反射、类加载、静态代理,jdk动态代理,cglib代理

一、 反射

反射是在程序运行状态下,动态获取类的结构(属性,构造器,方法,注解),动态的创建类对象然后调用类中的属性方法。反射的起源Class,Class中包含类反射要使用的API

获取Class的方法

java 复制代码
public class Student{
    private Integer sId;
    private String sName;

    private Integer getsId() {
        return sId;
    }

    private void setsId(Integer sId) {
        this.sId = sId;
    }

    private String getsName() {
        return sName;
    }

    private void setsName(String sName) {
        this.sName = sName;
    }
    public Student(Integer sId, String sName) {
        this.sId = sId;
        this.sName = sName;
    }
}

反射的方法:

  1. 获取类类型 对象

Class<Student> stu = Student.class

0.5)获取类 对象

Student stuObj = stu.new Instance() //默认获取无参构造方法

等价于

Student stuObj = stu.getConstructor().new Instance()

1)获取属性

Field sName = stu.getDeclaredField(''sName'')

sName.setAccessible(true)

Field sId = stu.getDeclaredField("sId")

sId.setAccessible(true)

属性设置值

sName.set(stuObj,''张三'')

sId.set(stuObj,1)

2)获取方法

Method getsId = stu.getMethod("getsId")

getsId.invoke(stuObj)

  1. 获取构造方法

Constructor c = stu.getConstructor(Integer.class,String.class)

Student s = c.new Instance(1,"张三")

注意事项:

反射获取方法,构造方法,属性方法中 方法名都有加Declared 与 不加Declared。

不加Declared:能够获取父子类中所有public修饰的方法

追加Declared:能够获取当前类中所有修饰符的方法

二)类加载

方法区:放置读取的.class文件

堆区:放置class文件生成的class对象

类加载的过程:

1)转载:查找并加载class文件

2)链接:

验证:验证字节码文件是否符合JVM规范。

准备:为类的静态变量分配内存,初始化化默认值

解析:类中的符号引用转换为直接引用

3)初始化:为类的静态变量赋予正确的初始值

三)Proxy 代理模式

Spring 框架:

IOC控制反转:把项目javabean对象的创建以继生命周期交给spring框架管理

需要使用bean对象时,直接从Spring容器(bean对象的容器)中获取。

利用java的反射,实例化bean对象

AOP面向切面编程:两种动态代理实现

jdk动态代理:实现接口

cglib动态代理:单独的类,没有实现接口

在不修改源代码的情况下扩展功能

静态代理:

目标对象:执行类中方法

代理对象:代理对象中包含目标对象,调用执行对象时可以额外添加功能

注意:静态代理是提前写死的.class文件,并且两个对象类实现同一个接口。跟接口耦合性太高,改动麻烦。

动态代理:

jdk动态代理:

实现InvocationHandler接口,重写invoke方法

1)第一种方式: 直接调用invoke方法

我们在其中内置一个Object对象用来实现对目标方法的调用

java 复制代码
public class SqlsessionutilProxyJDK implements InvocationHandler {
    private Object obj; //代表目标对象

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        if ("get".startsWith(name)||"select".startsWith(name)){
            Object invoke = method.invoke(obj, args);
            return invoke;
        }else {
            try {
                SqlSession session = SqlSessionUtil.getSession();
                Object invoke = method.invoke(obj, args);
                session.commit();
                return invoke;
            } catch (Exception e) {
                SqlSessionUtil.rollbackSession();
                throw new RuntimeException(e);
            }
        }
    }
}

在Test类中

复制代码
SqlsessionutilProxyJDK sqlsessionutilProxyJDK = new SqlsessionutilProxyJDK();
Object[] objects = {2,"在职"};
EmpService o =(EmpService) Proxy.newProxyInstance(new         EmpServiceImpl().getClass().getClassLoader(), new         EmpServiceImpl().getClass().getInterfaces(), new EmpServiceProxyJDK());
Method set = new EmpServiceImpl().getClass().getMethod("set", Integer.class, String.class);
sqlsessionutilProxyJDK.setObj(new EmpServiceImpl());
sqlsessionutilProxyJDK.invoke(o, set, objects);

2)简化方式:调用代理对象的相应方法

java 复制代码
public class SqlsessionutilProxyJDK implements InvocationHandler {
    private Object obj;

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

    public Object proxyInstance(Object obj){
        this.obj = obj;
        Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);
        return o;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        String name = method.getName();
        if ("get".startsWith(name)||"select".startsWith(name)){
            Object invoke = method.invoke(obj, args);
            return invoke;
        }else {
            try {
                SqlSession session = SqlSessionUtil.getSession();
                Object invoke = method.invoke(obj, args);
                session.commit();
                return invoke;
            } catch (Exception e) {
                SqlSessionUtil.rollbackSession();
                throw new RuntimeException(e);
            }
        }
    }
}

在Test类中:

cglib代理:

针对没有接口的类实现代理,实质上是创建这个类的子类,子类对象是代理对象,这个类对象是目标对象

需要在pom文件中引入第三方jar包 。如果在普通的java项目中,还需要有该jar包对应的依赖,但在Maven中会自动添加该jar包的依赖。

java 复制代码
<!--        cglib-->
        <dependency>
            <groupId>cglib</groupId>
            <artifactId>cglib</artifactId>
            <version>3.2.12</version>
        </dependency>
java 复制代码
public class CGLIBProxy implements MethodInterceptor {
    public Object getProxyInstance(Object obj){
        Enhancer enhancer= new Enhancer();
        enhancer.setSuperclass(obj.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("执行拓展功能");
        Object o1 = methodProxy.invokeSuper(o, objects);
        return o1;
    }
}

在测试类中

相关推荐
吾与谁归in10 小时前
【C#设计模式(13)——代理模式(Proxy Pattern)】
设计模式·c#·代理模式
OkeyProxy18 小时前
什麼是ISP提供的公共IP地址?
代理模式·proxy模式·ip地址·isp·海外ip代理
kikyo哎哟喂1 天前
Java 代理模式详解
java·开发语言·代理模式
hxj..2 天前
【设计模式】代理模式
java·设计模式·代理模式·动态代理
武子康2 天前
Java-05 深入浅出 MyBatis - 配置深入 动态 SQL 参数、循环、片段
java·sql·设计模式·架构·mybatis·代理模式
武子康3 天前
Java-04 深入浅出 MyBatis - SqlSessionFactory 与 SqlSession DAO与Mapper 代理模式
java·mysql·spring·mybatis·springboot·代理模式
南城花随雪。4 天前
Mybatis框架之代理模式 (Proxy Pattern)
mybatis·代理模式
JhonKI6 天前
【算法】动态规划中01背包问题解析
算法·动态规划·代理模式
OkeyProxy7 天前
如何恢復電腦IP地址的手動設置?
代理模式·ip·ip地址·代理服务器·海外ip代理
无限大.10 天前
动态规划与贪心算法:核心区别与实例分析
贪心算法·动态规划·代理模式