文章目录
代理模式
java
代理模式:
当我们要去访问一个目标类的时候,不是直接去访问这个目标类,而是去访问这个目标类的代理类,由这个代理类去调用目标类。
也就是我们间接的去访问目标类。
代理模式的作用
java
代理模式的作用:
我们可以在代理类调用目标类之前或之后去添加一些预处理和后处理的操作,来扩展一些不属于目标类的功能,也就是不侵入目标类。
比如说:
1.在方法开始和结束前记录日志,
2.在方法执行前进行额外的参数校验。
3.进行事务管理,
4.权限校验等
总的来说,代理模式就是实现了"功能增强"和"控制访问"
代理模式是一种设计思想,在实际实现上又分为"静态代理"和"动态代理"。
静态代理
java
静态代理:
1.代理类需要自己手动实现,
2.同时需要代理的目标类是确定明确的。
优点:静态代理实现起来比较简单,更容易让人理解。
缺点:当确定的目标类发现改变时,所有的代理类都得改变,会牵一发而动全身,不利于功能的增强和拓展。
动态代理
java
动态代理 基于反射机制
在程序执行过程中,使用jdk的反射机制,创建代理类对象,并动态得指定要代理的目标类。
也就是说:动态代理是一种创建java对象的能力,让你不用new对象。
什么是动态代理?
1.使用jdk的反射机制,创建对象的能力,创建的是代理类的对象。而不用你创建类文件,不用写Java文件。
2.动态是指在程序执行时,调用jdk提供的方法才能创建代理类的对象。
特点: 无侵入式的给代码增加额外的功能
动态代理代理的目标类是活动的,是可设置的
1.不用创建代理类
2.可以给不同的目标随时创建代理
动态代理的两种方式
java
1.JDK动态代理:
使用java反射包中的类和接口实现动态代理的功能。
反射包java.lang.reflect里的三个类:InvocationHandler,Method,Proxy.
2.cgli动态代理:cglib是第三方的工具库创建代理对象。
cglib的原理是继承,cglib通过继承目标类,创建他的子类,在子类中重写父类中同名的方法,实现功能的修改。
1.JDK动态代理
java
JDK动态代理案例
我想看鸡哥表演,听鸡你太美和看打篮球,于是鸡哥的经纪公司开始筹划演唱会,开始定价门票.
java
public class Test {
public static void main(String[] args) {
//1.获取代理的对象,找到鸡哥的经纪公司,我大喊鸡哥
BigStar bigStar = new BigStar("鸡哥");
Star proxy = ProxyUtil.createProxy(bigStar);
//2.经纪公司请出鸡哥唱歌,我要点歌,我要听鸡你太美
String resurl = proxy.sing("鸡你太美");
System.out.println(resurl);
//3.经纪公司请出鸡哥跳舞
proxy.dance();
}
}
java
总结: 整个演唱会中体现了"功能解耦","功能增强","权限控制"等.
1.JAVA提供了什么API帮我们创建代理?
2.newProxyInstance()方法在创建代理时,需要接几个参数,每个参数的含义是什么?
3.通过InvocationHandler的invoke方法指定代理干的事时,这个invoke会被谁调用?要接几个参数?
在我听鸡哥唱歌看表演的整个过程中
经纪公司做了增强功能,准备了演出的各个环节,搭建舞台,收门票等工作;
鸡哥直接上台表演即可,不用操心舞台怎么搭建,门票收多少钱,
我也提出了我要听鸡你太美的诉求.
代理类实现代理的过程代码
java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyUtil {
/**
* 方法的作用:
* 给BigStar对象创建一个代理
* 返回值就是创建的代理对象
*
* 形参: 被代理的Bigstar对象
* 返回值: 给Bigstar创建的代理对象
* @param bigStar
*/
public static Star createProxy(BigStar bigStar){
/**
* newProxyInstance()参数说明
* 参数一: 用于指定用哪个类加载器去加载生成的代理类;
* 参数二: 指定接口,这些接口用于指定生成的代理长什么样,也就是有哪些方法
* 参数三: 用来指定生成的代理对象要干什么事情
*/
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
/**
* 参数一: "proxy"是代理的对象
* 参数二: "method"是要运行的方法sing
* 参数三: "args"是调用sing方法时,传递的实参
*/
if("sing".equals(method.getName())){
System.out.println("经纪公司准备话筒,收钱");
}else if("dance".equals(method.getName())){
System.out.println("经纪公司准备舞台,收钱");
}
//一切准备就绪后,开始请出大明星了
return method.invoke(bigStar,args);
}
}
);
return star;
}
}
匿名内部类的lambda写法
java
//lambda表达式不关心对象名也不关心方法名
Star star = (Star) Proxy.newProxyInstance(
ProxyUtil.class.getClassLoader(),
new Class[]{Star.class},
(proxy, method, args) -> {
/**
* 参数一: 代理的对象
* 参数二: 要运行的方法sing
* 参数三: 调用sing方法时,传递的实参
*/
if("sing".equals(method.getName())){
System.out.println("经纪公司准备话筒,收钱");
}else if("dance".equals(method.getName())){
System.out.println("经纪公司准备舞台,收钱");
}
//一切准备就绪后,开始请出大明星了
return method.invoke(bigStar,args);
}
);
return star;
反射概述
java
Java反射机制
在程序运行时通过Class类的API动态地获取一个类的信息(属性和方法)并且能够操作该类的属性和方法的能力.
1.获取class对象:Class
2.构造方法:Constructor
3.字段(成员变量):Field
4.成员方法:Method
获取Class对象的三种方式
java
public class ReflectTest {
public static void main(String[] args) throws ClassNotFoundException {
/**
* 获取class对象的三种方式
* 1.Class.forName("全类名");
* 2.类名.class
* 3.对象.getClass();
*/
//1.第一种方式
//全类名: 包名 + 类名
//最为常用
Class clazz1 = Class.forName("com.lei.proxy.reflect.Student");
System.out.println("方式一获取:"+clazz1);
//2.第二种方式
//一般更多的是当做参数进行传递
Class clazz2 = Student.class;
System.out.println("方式二获取:"+clazz2);
//3.第三种方式
Student student = new Student();
Class clazz3 = student.getClass();
System.out.println("方式三获取:"+clazz3);
System.out.println(clazz1 == clazz2);
System.out.println(clazz2 == clazz3);
}
}
获取构造方法
反射总结
java
反射作用:
1.获取一个类里面所有的信息,获取到了之后,再执行其他的业务逻辑
2.结合配置文件,动态地创建对象并调用方法
获取class字节码文件对象的三种方式
1.Class.forName("全类名")
2.类名.class
3.对象,getClass();
如何获取构造方法,成员变量,成员变量
get: 获取 set: 设置
Constructor: 构造方法 parameter: 参数
Field: 成员变量 Modifiers: 修饰符
Method: 方法 Declared: 私有的
单例模式
bash
单例模式:
在程序运行过程中,一个类只有一个实例对象,也就是只会new一次.
为什么需要单例?
程序过程中,有的实例,会被反复的调用,如果这个实例反复的被创建,反复的被销毁是一种性能的消耗.