20230316------反射机制,静态代理和动态代理

反射机制

1.通过反射可以做什么?
    反射机制 java.lang.reflect.* 包下面的类库
    我们通过反射机制可以操作一个类的字节码!

    Test.java  --> 编译 javac编译后生成  -> Test.class
    通过反射机制可以操作 Test.class字节码

2.类中都有什么?
  java.lang.reflect Class Field  --》属性
  java.lang.reflect Class Method--》方法
 java.lang.reflect  Class Constructor --》构造方法

public class ReflectTest02 {
    public static void main(String[] args) {
        Class clazz;
        {
            try {
                clazz = Class.forName("com.wwh.Student");
                Method[] declaredMethods = clazz.getDeclaredMethods();
                for (Method dec : declaredMethods) {
                    System.out.println(dec);
                }
                Field[] declaredFields = clazz.getDeclaredFields();
                for (Field f:declaredFields){
                    System.out.println(f);
                }
                Constructor[] constructors = clazz.getConstructors();
                for (Constructor constructor:constructors){
                    System.out.println(constructor);
                }
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
}

3.要想操作一个类的字节码,首先要获取字节码!
如何获取呢? 三种方式获取
            Class clazz = Class.forName("com.liushao.reflect.demo01.Student");//第一种

            Class clazz2 = Student.class;//第二种

            Student student = new Student();
            Class clazz3 = student.getClass();//第三种

public class ReflectTest01 {
    public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        Class clazz1=Class.forName("com.wwh.Student");
        Object o= clazz1.newInstance();//创建这个类对象表示的类的一个新实例。

        Student student=new Student();
        Class clazz2=student.getClass();
        Object o2= clazz2.newInstance();

        Class clazz03=Student.class;
        Object o3= clazz03.newInstance();
    }
}

4.我们获取到一个类之后能做什么?

5.反射的应用场景
 Spring--IOC
 Spring--AOP
 很多框架中  mybatis  dubbo  rocketmq

6.代理模式 
   好处:
   客户端直接使用的都是代理对象,不知道真实对象是谁,我们的代理对象可以和真实对象之间起到中介的作用.

   代理对象完全包含真实对象,客户端使用的都是代理对象的方法,和真实对象没有直接关联!
   代理模式的职责: 把不是真实对象该做的事情从真实对象上撇开--》 职责分离!

   6.1分类
    静态代理
        在程序运行前已经存在代理类的字节码文件,代理对象和真实对象的关系在程序运行前就已经确定了
     [代理类和对象由我们进行创建对象]
    动态代理
        代理类是在程序运行期间由JVM通过反射机制动态生成的,所以不存在代理类字节码文件,动态生成字节码对象,
    代理对象和真实对象的关系是在程序运行期间才确定的 (代理类和对象不需要我们进行创建!)

   6.3 动态代理的实现方式
       针对于实现类有接口使用JDK动态代理
       针对于实现类没有接口的使用CGLIB动态代理

     6.4  动态代理的实现机制
        参见画图
    
   6.5 静态代理

  
    6.6  动态代理
       动态代理和静态代理的区别
       静态代理在编译时就已经实现,编译完成后代理类就是一个class文件
       动态代理在运行时动态生成的,编译完成后没有实际的class文件,而是在运行时动态生成字节码,并加载JVM中

       特点:
       java.lang.reflect Class Proxy

       public static Object newProxyInstance(ClassLoader loader,  //指定当前对象使用的类加载器
                                      Class<?>[] interfaces,  //目标对象实现的接口类型
                                      InvocationHandler h)   //事件处理器

                              
     Object  // 返回一个指定接口的代理类实例

     Object invoke(Object proxy,
              Method method,
              Object[] args)
          在代理实例上处理方法调用并返回结果
    jar 

    cglib 动态代理
    它是一个第三方的类库

    ASM框架

7.例子


    第一个静态代理的例子

public interface IEmployeeService {
    public void save(String name,String upwd);
}




public class EmployeeServiceImpl implements IEmployeeService{
    @Override
    public void save(String name, String upwd) {
        System.out.println("保存"+name+"\t"+upwd);
    }
}



public class MyTransactionManager {
    public void begin(){
        System.out.println("开启事务");
    }
    public void commit(){
        System.out.println("提交事务");
    }
    public void rollback(){
        System.out.println("回滚事务");
    }
}
public class EmployeeServiceProxy implements IEmployeeService{
    private IEmployeeService target;//接口

    public void setTarget(IEmployeeService target) {
        this.target = target;
    }
    private MyTransactionManager mt;

    public void setMt(MyTransactionManager mt) {
        this.mt = mt;
    }
    @Override
    public void save(String name, String upwd) {
        try {
            mt.begin();
            target.save(name, upwd);//调用sava方法。
            mt.commit();
        }catch (Exception e) {
           mt.rollback();
           e.printStackTrace();
        }
    }
}



public class Test {
    public static void main(String[] args) {
        MyTransactionManager mt = new MyTransactionManager();
        EmployeeServiceProxy esp = new EmployeeServiceProxy();
        EmployeeServiceImpl esi = new EmployeeServiceImpl();
        esp.setTarget(esi);
        esp.setMt(mt);
        esp.save("wwh","123");
    }
}

第二个静态代理的例子: 

public interface IUser {
    public void save();
}



public class UserDaoImpl implements IUser{
    @Override
    public void save() {
        System.out.println("保存数据");
    }
}
public class UserDaoProxy implements IUser{
    private IUser target;
    public UserDaoProxy(IUser target) {
        this.target = target;
    }
    @Override
    public void save() {
        //
       target.save();
    }
}



public class Test {
    public static void main(String[] args) {
        UserDaoImpl ud=new UserDaoImpl();
        UserDaoProxy proxy=new UserDaoProxy(ud);
        proxy.save();
    }
}

第三个动态的例子:
   

public interface IUserDao{
    void save();
}




public class UserDao implements IUserDao{
    @Override
    public void save() {
        System.out.println("数据保存");
    }
}
public class UserProxyFactory {
    private Object target;

    public UserProxyFactory(Object target) {
        this.target = target;
    }
    //为目标对象生成代理对象
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        System.out.println("开启事务");
                        Object invokeValue = method.invoke(target, args);
                        return null;
                    }
                });
    }
}



public class TestProxy {
    public static void main(String[] args) {
        IUserDao target=new UserDao();
        System.out.println(target.getClass());

        IUserDao proxy=(IUserDao)new UserProxyFactory(target).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.save();
    }
}

第四个例子:拦截器intercept的使用。

普通类,要被代理的对象。
public class UesrDao {
    public void save(){
        System.out.println("数据保存");
    }
}



//代理类
public class ProxyFactory implements MethodInterceptor {
    public Object target;//目标对象

    public ProxyFactory(Object target) {
        this.target = target;
    }
    public Object getProxyInstance(){
        //工具类
        Enhancer en =new Enhancer();
        //设置父类
        en.setSuperclass(target.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类代理对象
        return en.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("开启事务");
        Object invokeValue = method.invoke(target, objects);
        System.out.println("提交事务");
        return null;
    }
}




//测试类
public class TestProxy {
    public static void main(String[] args) {
        UserDao target = new UserDao();
        System.out.println(target.getClass());
        UserDao proxy=(UserDao) new ProxyFactory(target).getProxyInstance();
        System.out.println(proxy.getClass());
        proxy.save();
    }
}

      静态代理:静态代理就是,先一个接口,接口里面有一个方法,一个普通类去实现接口。一个代理类,也去继承这个接口,里面去创建普通类对象,含参构造方法,重写接口方法,里面用普通类对象调用接口方法。测试的时候,创建两个实例对象,将普通类放入代理类的构造,接着调用方法。

     动态代理:

     一种含接口的动态代理:还是一个接口,一个实现接口的普通类,一个不再去实现接口的代理类,这个代理类写一个方法,用到了,Proxy类,Method类,IncocationHandler类。

核心代码:

public Object getProxyInstance(){
    return Proxy.newProxyInstance(target.getClass().getClassLoader(),
            target.getClass().getInterfaces(), new InvocationHandler() {
                @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                    System.out.println("开启事务");
                    Object invokeValue = method.invoke(target, args);
                    return null;
                }
            });
}

   一种不含接口的动态代理:引用资源包cglib。

跟上一个动态代理一样,只是普通类自己写方法体,代理类需要去继承MethodInterceptor类

重写Intercept方法。

然后getProxyInstance方法不一样。

核心代码::

public Object getProxyInstance(){
    //工具类
    Enhancer en =new Enhancer();
    //设置父类
    en.setSuperclass(target.getClass());
    //设置回调函数
    en.setCallback(this);
    //创建子类代理对象
    return en.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
    System.out.println("开启事务");
    Object invokeValue = method.invoke(target, objects);
    System.out.println("提交事务");
    return null;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值