就是正在运行,动态获取这个类的所有信息。
1,反编译:.class–>.java
2.通过反射机制访问java对象的属性,方法,构造方法等;
Jdbc 加载驱动-----
Spring IOC
框架
创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式 、建造者模式、原型模式。
结构型模式,共七种:适配器模式、装饰器模式、代理模式、外观模式、桥接模式、组合模式、享元模式。
行为型模式,共十一种:策略模式、模板方法模式、观察者模式、迭代子模式、责任链模式、命令模式、备忘录模式、状态模式、访问者模式、中介者模式、解释器模式。
正在运行,动态获取类的信息
java源代码—.class文件。字节码
spring框架。ORM.
class.forName(“ ”)
forName.newinstance()
连接jdbc
springioc 底层使用反射机制+dom4j
Hibernate spring框架 使用反射机制
方法
forName…getMonthods()
属性
forName…getFields()
设置私有 会没有权限 但是可以 类.setAccess(true)
方便维护 扩展性提高 减少冗余代码 提高可读性
降低耦合度
先了解需求 不要立马写代码
先思考怎么重构代码
特点:解决动态获取配置文件信息
使用分布式配置中心 使用zookeeper搭建
保证在一个jvm中,只能存在一个实例,保证对象唯一性。
Servlet struts2 spring(默认单例) springmvc 连接池 线程池 枚举 常量
优点: 节约内存 重复利用 方便管理
缺点:线程安全问题
: 类初始化,就会加载该对象。线程安全,调用性高。
类初始化,就会创建对象。天生线程安全。可以让多个线程访问,效率高。如果不使用对象的时候,浪费内存。
new的对象存放在 永久区。垃圾回收不会回收
1.将构造函数私有化
:真正需要的时候才会创建该对象,具备加载功能。
天生线程不安全,需要解决线程安全问题。要加syn锁,只能一个线程访问,所以效率很低
结合懒汉饿汉优点。真正需要的时候才会创建该对象,线程安全
优势:兼顾了懒汉模式的内存优化(使用时才初始化)以及饿汉模式的安全性(不会被反射入侵)。
劣势:需要两个类去做到这一点,虽然不会创建静态内部类的对象,但是其 Class 对象还是会被创建,而且是属于永久带的对象。
实现简单 调用性高,枚举本身就是单例。
缺点: 没有延迟加载
定义常量,具备jvm保证单例 只能创建一次
可以防止反射攻击。
注意:枚举只能用@Getter 不能Data.会报错
(jvm本质冲排序原因,会初始化多次,不建议使用)
单线程 不会发生重排序
重排序 可能会导致 创建多个对象。
饿汉式:
public class Hungry {
private static Hungry hungry = new Hungry();
private Boolean flag = false;
// 1. 私有化 构造函数 单例防止反射
private Hungry() {
// Lazy.preventAttacks();
if(!flag){
flag = true;
}else {
throw new RuntimeException("已经被创建,违反单例模式。");
}
}
public static Hungry getInstance() {
return hungry;
}
public static void main(String[] args) {
Hungry h1 = Hungry.getInstance();
Hungry h2 = Hungry.getInstance();
System.out.println(h1 == h2); // true
}
懒汉式
public class Lazy {
private static Lazy lazy;
private static Boolean flag = false;
private Lazy() {
preventAttacks();
}
/**
* 此方法在构造函数中使用
* 单例防止反射漏洞攻击
* 单例 只执行一次构造函数,若能进构造函数,说明还未创建对象。
* flag改为true之后,此方法将不再被执行
* 若进入true此判断,说明 已经被执行过一次。
*
*/
public static void preventAttacks() {
if(!flag){
flag = true;
}else {
throw new RuntimeException("已经被创建,违反单例模式。");
}
}
public static Lazy getInstance(){
if (lazy == null){
lazy = new Lazy();
}
return lazy;
}
public static void main(String[] args) {
Lazy l1 = Lazy.getInstance();
Lazy l2 = Lazy.getInstance();
System.out.println(l1 == l2);//true
}
}
静态内部类
public class StaticInner {
private static Boolean flag = false;
private StaticInner() {
if(!flag){
flag = true;
}else {
throw new RuntimeException("已经被创建,违反单例模式。");
}
}
/**
* 静态内部类
*/
private static class InnerDemo{
private static StaticInner staticInner = new StaticInner();
}
public static StaticInner getInstance(){
return InnerDemo.staticInner;
}
public static void main(String[] args) {
StaticInner s1 = StaticInner.getInstance();
StaticInner s2 = StaticInner.getInstance();
System.out.println(s1 == s2);//true
}
}
枚举
@Getter
public enum StatusEnum {
HTTP_200(200,"成功"),
;
private Integer code;
private String msg;
private Boolean flag = false;
StatusEnum() {
if(!flag){
flag = true;
}else {
throw new RuntimeException("已经被创建,违反单例模式。");
}
}
StatusEnum(Integer code, String msg) {
this.code = code;
this.msg = msg;
}
public static void main(String[] args) {
System.out.println(HTTP_200.getCode());//200
}
}
双重锁
public class DoubleCheck {
private static DoubleCheck doubleCheck;
private static Boolean flag = false;
private DoubleCheck() {
if(!flag){
flag = true;
}else {
throw new RuntimeException("已经被创建,违反单例模式。");
}
}
public static DoubleCheck getInstance(){
if(doubleCheck == null){
// 若不加锁 假设2个线程 当是null的时候。2个都可以进来。那么1线程创建完,2又创建一次。 所以加锁后还要在判断一次。
synchronized (DoubleCheck.class){
if(doubleCheck == null){
doubleCheck = new DoubleCheck();
}
}
}
return doubleCheck;
}
public static void main(String[] args) {
DoubleCheck d1 = DoubleCheck.getInstance();
DoubleCheck d2 = DoubleCheck.getInstance();
System.out.println(d1 == d2);
}
}