浅谈Java反射和代理

目录

一、反射

        什么是反射?

        获取类信息的三种方式

        反射进行赋值

            方法一(直接暴力赋值)

        方法二(Method反射调用自身) 

二、代理

        什么是代理

        静态代理

                静态代理的好处

        接口实现

        实现类

        代理类

  jdk动态代理

 Cglib实现代理

AOP

         代理目标接口

        实现类

        增强类

        main方法

        spring-aop.xml


一、反射

        什么是反射?

                反射是运行状态中,任意一个类都能获取这个类的所有属性和方法,任意一个对象都能调用它的一个方法和属性,动态获取类信息和动态获取对象内容。

        获取类信息的三种方式

                1、对象.getClass() 2、类.forName("java.lang.String") 3、类名.class

//方法一:
Class<?> clas = Class.forName("java.lang.Object");
//方法二:通过类的名字打打点class,如
Class<?> clas1 = Object.class;
//方法三:通过该类的对象去调用getClass()方法,如
Class<?> clas2 = new Object().getClass();
System.out.println(clas.toString());
//它们的结果都是: class java.lang.Object

        反射进行赋值

            方法一(直接暴力赋值)

                根据方法名字来获得属性对象,破坏掉私有属性,然后赋值

                

public class A {
    private String a;
}
public class Demo0813 {
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        A al = new A();

       Class c1 = al.getClass();

        Field x = c1.getDeclaredField("a");

        x.setAccessible(true);
        x.set(al,"张三");

        System.out.println(x.get(al));

    }
}

 输出为

张三

        方法二(Method反射调用自身) 

        指定setXxx方法,通过Method反射调用自身;关键方法invoke(Obkect obj, Object…args)

public class Demo0813 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {


        Class<?> aClass = Class.forName("entity.A");

        Object ol = aClass.newInstance();

        Method setName = aClass.getDeclaredMethod("setName",String.class);
        setName.setAccessible(true);
        setName.invoke(ol,"李四");

        Method getName = aClass.getDeclaredMethod("getName");
        getName.setAccessible(true);
        Object invoke = getName.invoke(ol);

        System.out.println(invoke);

    }
}

输出为

李四

二、代理

        什么是代理

                代理是一种设计模式;给目标对象提供一个代理对象,并且由代理对象控制对目标对象的引用。

        目的是:

                通过代理对象的方式间接的访问目标对象,防止直接访问目标对象给系统带来不必要的复杂性

                通过代理业务对原有业务进行增强

        代理又分为静态代理和动态代理

        静态代理

                静态代理是由程序员创建或工具生成代理类的源码,再编译代理类,即代理类和委托类的关系再程序运行前就已经存在。

                静态代理的好处

                        可以隐藏委托类的具体实现;

                        可以在不改变委托类的情况下增加额外的操作

        接口实现

public interface Singer {
    void singMethod();

    int sing(Integer i);

}

        实现类

public class Cat implements Singer {
    @Override
    public void singMethod() {
        System.out.println("cat 唱歌");
    }

    @Override
    public int sing(Integer i) {
        System.out.println("cat 跳舞");
        return i;
    }
}

        代理类

public class CatProxy implements Singer {
    Cat cat = new Cat();
    @Override
    public void singMethod() {
        System.out.println("方法执行前");
        cat.singMethod();
        System.out.println("方法执行后");
    }

    @Override
    public int sing(Integer i) {
        System.out.println("方法执行前");
        int haha = cat.sing(i);
        System.out.println("方法执行后");
        return haha;
    }
}

        输出为

方法执行前
cat 唱歌
方法执行后
-----------------------------
方法执行前
cat 跳舞
方法执行后
666

  jdk动态代理

                 JDK动态代理基本接口实现,通过接口指向实现类实例的多态方式,可以有效地将具体实现与调用解耦,便于后期的修改和维护。

public class CatUser {
    public static void main(String[] args) {
        Cat cat = new Cat();
        Money money = new Money(cat);

      Object a = Proxy.newProxyInstance(Cat.class.getClassLoader(),Cat.class.getInterfaces(),money);

      if (a instanceof  Singer){
          Singer singer = (Singer) a;
          singer.singMethod();

          System.out.println(singer.sing(3));

          singer.toString();
      }


    }

    static class Money implements InvocationHandler{
        private Singer singer;

        public Money(Singer singer){
            this.singer = singer;
        }

        @Override
        public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
            System.out.println("快乐如此简单");
            Object invoke = method.invoke(singer,objects);
            return invoke;
        }
    }


}

输出为

快乐如此简单
cat 唱歌
快乐如此简单
cat 跳舞
3
快乐如此简单

 Cglib实现代理

        

public class TargetProxy {

    static <T> Object getProxy(T t) {
        Enhancer en = new Enhancer(); //帮我们生成代理对象
        en.setSuperclass(t.getClass());//设置要代理的目标类
        en.setCallback(new MethodInterceptor() {//代理要做什么
            @Override
            public Object intercept(Object object, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("执行方法前。。。");
                //调用原有方法  
                Object invoke = methodProxy.invokeSuper(object, args);
                // Object invoke = method.invoke(t, args);// 作用等同与上面。
                System.out.println("执行方法后。。。");
                return invoke;
            }
        });
        return en.create();
    }
}

输出为

执行方法前。。。
method1 running ...
执行方法后。。。

jdk实现InvocationHandler类 重写invoke实现切面,cglib实现MethodInterceptor类 重写intercept实现切面
jdk代理是生成代理对象 会调用invoke方法,cglib利用ASM技术 直接编译到class内
jdk代理是作用在interface上, cglib代理可以是任意类 final除外

AOP

         代理目标接口

public interface TargetInteface {
    void method1();
    void method2();
    int method3(Integer i);
}

        实现类

        

public class Target implements TargetInteface{

    /*
    * 需要增强的方法,连接点JoinPoint
    **/
    public void method1() {
        System.out.println("method1 running ...");
    }

    public void method2() {
        System.out.println("method2 running ...");
    }

    public int method3(Integer i) {
        System.out.println("method3 running ...");
        return i;
    }
}

        增强类

public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {

    /*
    * 通知/增强
    **/
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        System.out.println("前置环绕通知");
        Object proceed = methodInvocation.proceed();
        System.out.println("后置环绕通知");
        return proceed;
    }

    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("后置返回通知");
    }

    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("前置通知");
    }
}

        main方法

public class AopTest {
    public static void main(String[] args) {
        ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");
        Target targetProxy = (Target) appCtx.getBean("targetProxy");
        targetProxy.method1();
    }
}

        spring-aop.xml

        

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="target" class="com.heaboy.aopdemo.aop.Target"/>

    <bean id="targetAdvice" class="com.heaboy.aopdemo.aop.TargetAdvice"/>

    <bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="target"/> <!--被代理的类-->
        <property name="interceptorNames" value="targetAdvice"/>  <!--如果用多种增强方式,value的值使用逗号(,)分割-->
        <property name="proxyTargetClass" value="true"/>
        <property name="interfaces" value="com.heaboy.aopdemo.aop.TargetInteface"/>  <!--target实现的接口-->
    </bean>
</beans>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

herrybody

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值