一直想专门写个Spring源码的博客,工作了,可以全身性的投入到互联网行业中。虽然加班很严重,但是依然很开心。趁着凌晨有时间,总结总结。

首先spring,相信大家都很熟悉了。

1、轻量级  零配置,API使用简单

2、面向Bean  只需要编写普通的Bean(一个Bean代表一个对象)

3、松耦合 充分利用AOP思想 )(各自可以独立开发,然后整合起来运行)

4、万能胶 与主流框架无缝集成 (Mybatis dubbo等等 )

5、设计模式 将Java中经典的设计模式运用的淋漓尽致

Spring解决企业级应用开发的负责设计,简化开发。

1,基于POJO的清理爱你国际和最小侵入性(代码的嵌套,独自开发合起来运行)

2,通过依赖注入和面向接口松耦合

3、基于切面(典型的事务管理!!日志)和惯性进行声明式编程

4、通过切面和模板减少版式代码

主要通过,面向Bean、依赖注入以及面向切面三种方式达成

Spring提供了IOC容器,通过配置文件或者注解的方式来管理对象之间的依赖关系

A a = new A()//实例化后用一个变量保存下来(匿名对象)    ------------------》Spring用IOC容器 存储起来~

a.c()  //必须初始化才运行  -----------------------> Spring帮忙初始化,实例化(控制器给了spring)

最终实现了 依赖注入:

@autowrite Interfa A a   //自动吧他的实现类注入进来

@Resource(“aa”)//IOC容器种类的id为“aa”的对象自动注入到这里

@autowrite A a  //根据类型自动注入

Spring的注入方式

1、 setter

2、 构造方法

3、强制赋值

面向切面,AOP核心思想--解耦! 把一个整体拆开,分别开发,发布时候,再组装到一起运行,切面就是规则!

比如 事务;

开启事务 执行事务 事务回滚 关闭事务     这就是规则!!!!!!

这种有规律的,就可以认为他是固定的,可以单独拿出来开发设计,作为一个模块(比如日志啊)。

AOP就是个编程思想而已

关于Spring的使用,特点,网上资料很多,大家可以自己找找学习下。本博客主要对于源码进行解读。

在典型的面型对象开发方式中,可能要将日志记录语句放在所有方法和Java类种才能实现日志功能。而在AOP方式中,可以反过来将日志服务模块化,并以声明的方式将他们应用到需要日志的组件上。Java类不需要知道日志服务的存在,也不想需要考虑相关的代码。

AOP的功能完全集成到了Spring事务管理、日志和其他各种特性的上下文中

authentication权限认证

Logging日志

Transctions Manager事务

Lazy Loading懒加载

Contex Process 上下文处理

Error Handler 错误跟踪(异常捕获机制)

Cache缓存

1、除了AOP以外的设计模式

a、 代理模式

b、工厂模式

c、单例模式

d、委派模式

e、策略模式

f、策略模式

g、原型模式

代理模式原理:

1、拿到被代理对象的引用,然后获取它的接口

2、JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口

3、把代理对象的引用拿到

4、重新动态生成一个class字节码

5、编译

动态代理 调用哪个方法就代理哪个方法

整个类 生成一个新 的类

大家认真仔细研究好代理模式,代理模式在Spring中 应用非常广泛!!!

JDK代理模式实现:

1、定义接口

2、定义实现接口的类

3、 代理类  ,代理类需要实现  InvocationHandler 接口,然后实现 invoke方法

 回顾一下,满足代理模式应用场景的三个必要条件,穷取法
1、两个角色:执行者、被代理对象
2、注重过程,必须要做,被代理对象没时间做或者不想做(怕羞羞),不专业
3、执行者必须拿到被代理对象的个人资料(执行者持有被代理对象的引用)

例:定义Persion接口

public interface Person {

    //寻找真爱、相亲
void findLove(); // String getSex();
//
// String getName(); }

实现这个接口

//小星星、单身
public class XiaoXingxing implements Person{ // private String sex = "女";
// private String name = "小星星"; @Override
public void findLove() {
// System.out.println("我叫" + this.name + ",性别:" + this.sex + "我找对象的要求是:");
System.out.println("高富帅");
System.out.println("有房有车的");
System.out.println("身高要求180cm以上,体重70kg");
} // public String getSex() {
// return sex;
// }
//
// public void setSex(String sex) {
// this.sex = sex;
// }
//
// public String getName() {
// return name;
// }
//
// public void setName(String name) {
// this.name = name;
// } }

代理类

//媒婆
public class Meipo implements InvocationHandler { private Person target; //被代理对象的引用作为一个成员变量保存下来了 在下面调用时候的 的 ///////////////////////// 下面的嗲用 //获取被代理人的个人资料为,为了能让他代理任何对象
public Object getInstance(Person target) throws Exception {
this.target = target;
Class clazz = target.getClass(); //利用反射机制(最终获得接口)
System.out.println("被代理对象的class是:" + clazz);
return Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this); //this这个参数 指的是 代理人 this.h 就是调用了媒婆的 invoke方法 this指的是invoke这个回调方法
}
//代理对象 会自动调用下面invoke方法
@Override
public Object invoke (Object proxy, Method method, Object[] args) throws Throwable{ System.out.println("我是媒婆:" + "得给你找个异性才行");
System.out.println("开始进行海选...");
System.out.println("------------");
///////////////////////////////////////////////////////////
//调用的时候 (利用反射机制调用) 对象名.方法名
method.invoke(this.target, args); 这个invoke不是方法名字的invoke 是的话 会陷入死循环
System.out.println("------------");
System.out.println("如果合适的话,就准备办事"); return null;
} }

测试:

public class TestFindLove {
public static void main(String[] args) { try { //
// Person obj = (Person)new Meipo().getInstance(new XiaoXingxing());
// System.out.println(obj.getClass());
// obj.findLove(); //原理:
//1.拿到被代理对象的引用,然后获取它的接口
//2.JDK代理重新生成一个类,同时实现我们给的代理对象所实现的接口
//3.把被代理对象的引用也拿到了
//4.重新动态生成一个class字节码
//5.然后编译 //获取字节码内容
// byte[] data = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{Person.class}); //生成字节码文件
// FileOutputStream os = new FileOutputStream("E:/GP_WORKSPACE/$Proxy0.class"); //将字节码输入到磁盘上
// os.write(data);
// os.close(); //是什么?
//为什么?
//怎么做?
//解释: 字节码 反编译后 可以查看

Person obj = (Person)new GPMeipo().getInstance(new XiaoXingxing()); //返回一个代理对象 代理出来的这个对象可以强转这个接口类
System.out.println(obj.getClass()); //这个Object对象 并不是 lcy的引用了 完全是一个新的对象
obj.findLove(); //动态代理 需要调用哪个方法 就调用哪个方法 整个类都是新的类了 新的字节码 } catch (Exception e) {
e.printStackTrace();
} }
}

也可以不用 JDK的任何东西 自己实现动态代理!!

不用jdk的任何东西!

首先规定有个InvocationHandler  有个 invoke方法

import java.lang.reflect.Method;

public interface GPInvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
}

实现个Proxy  里面有 InvocationHandler引用  有 newInstance的方法 classloader方法

import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method; import javax.tools.JavaCompiler;
import javax.tools.JavaCompiler.CompilationTask;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider; //生成代理对象的代码
public class GPPorxy { private static String ln = "\r\n"; public static Object newProxyInstance(GPClassLoader classLoader,Class<?>[] interfaces,GPInvocationHandler h){ try{
//1、生成源代码
String proxySrc = generateSrc(interfaces[0]); //2、将生成的源代码输出到磁盘,保存为.java文件
String filePath = GPPorxy.class.getResource("").getPath();
File f = new File(filePath + "$Proxy0.java");
FileWriter fw = new FileWriter(f);
fw.write(proxySrc);
fw.flush();
fw.close(); //3、编译源代码,并且生成.class文件
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
StandardJavaFileManager manager = compiler.getStandardFileManager(null, null, null);
Iterable iterable = manager.getJavaFileObjects(f); CompilationTask task = compiler.getTask(null, manager, null, null, null, iterable);
task.call();
manager.close(); //4.将class文件中的内容,动态加载到JVM中来 //5.返回被代理后的代理对象
Class proxyClass = classLoader.findClass("$Proxy0");
Constructor c = proxyClass.getConstructor(GPInvocationHandler.class); //拿到构造方法
f.delete(); return c.newInstance(h); }catch (Exception e) {
e.printStackTrace();
} return null;
} private static String generateSrc(Class<?> interfaces){
StringBuffer src = new StringBuffer();
src.append("package com.gupaoedu.vip.custom;" + ln);
src.append("import java.lang.reflect.Method;" + ln);
src.append("public class $Proxy0 implements " + interfaces.getName() + "{" + ln); src.append("GPInvocationHandler h;" + ln); src.append("public $Proxy0(GPInvocationHandler h) {" + ln);
src.append("this.h = h;" + ln);
src.append("}" + ln); for (Method m : interfaces.getMethods()) { //那么多方法 需要拿出来
src.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + ln); src.append("try{" + ln);
src.append("Method m = " + interfaces.getName() + ".class.getMethod(\"" +m.getName()+"\",new Class[]{});" + ln); //方法名 参数等等
src.append("this.h.invoke(this,m,null);" + ln);
src.append("}catch(Throwable e){e.printStackTrace();}" + ln);
src.append("}" + ln);
} src.append("}"); return src.toString();
}
}

classloader类

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; //代码生成、编译、重新动态load到JVM
public class GPClassLoader extends ClassLoader{ private File baseDir; public GPClassLoader(){
String basePath = GPClassLoader.class.getResource("").getPath();
this.baseDir = new java.io.File(basePath); //保存路径
} @Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
String className = GPClassLoader.class.getPackage().getName() + "." + name; //找到这个class文件
if(baseDir != null){
File classFile = new File(baseDir,name.replaceAll("\\.", "/") + ".class");
if(classFile.exists()){
FileInputStream in = null;
ByteArrayOutputStream out = null;
try{
in = new FileInputStream(classFile);
out = new ByteArrayOutputStream();
byte [] buff = new byte[1024]; //缓冲区
int len;
while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len);
} //全部读完
return defineClass(className, out.toByteArray(), 0,out.size()); //搞到jvm中去 }catch (Exception e) {
e.printStackTrace();
}finally{
if(null != in){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(null != out){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
classFile.delete();
} }
} return null;
} }

代理类媒婆  必须实现这个类

import java.lang.reflect.Method;

import com.gupaoedu.vip.proxy.jdk.Person;

public class GPMeipo implements GPInvocationHandler{

    private Person target;

    //获取被代理人的个人资料
public Object getInstance(Person target) throws Exception{
this.target = target;
Class clazz = target.getClass();
System.out.println("被代理对象的class是:"+clazz);
return GPPorxy.newProxyInstance(new GPClassLoader(), clazz.getInterfaces(), this);
} @Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("我是媒婆:得给你找个异性才行");
System.out.println("开始进行海选...");
System.out.println("------------");
method.invoke(this.target, args);
System.out.println("------------");
System.out.println("如果合适的话,就准备办事");
return null;
} }

注意 Java中 $符号的 约定俗成 被代理的类

JDK 必须 实现接口!!!!

满足代理模式应用场景的三个必要条件,

1、需要有两个角色  执行者 和 被代理对象

2、注重过程,必须要做,被代理对象不做

3、执行者必须拿到被代理对象的资料(执行者持有被代理对象的引用)

代理模式总结到底层就是:字节码重组! (字节码重组时候 对象要强制转换,必须要实现一个接口)

Java源代码--->编译---->字节码(在原始的加了东西)-->加载到jvm中

然后 cglib不需要,Spring主要用的cglib做动态代理 定义一个类   自动生成一个类 自动继承这个类 子类引用指向父类   看下面:

(同样做了字节码重组 事情)

是继承关系

public class YunZhongYu {

    public void findLove(){
System.out.println("肤白貌美大长腿");
} }

定义代理类:

import java.lang.reflect.Method;

import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy; public class GPMeipo implements MethodInterceptor{ // MethodInterceptor这是cglib里面的 //疑问?
//好像并没有持有被代理对象的引用
public Object getInstance(Class clazz) throws Exception{
//通过反射机制进行实例化 Enhancer enhancer = new Enhancer(); //用来动态生成class
//把父类设置为谁?
//这一步就是告诉cglib,生成的子类需要继承哪个类
enhancer.setSuperclass(clazz);
//设置回调
enhancer.setCallback(this); //业务逻辑 指的是下面的 intercept 回调方法 //第一步、生成源代码
//第二步、编译成class文件
//第三步、加载到JVM中,并返回被代理对象
return enhancer.create();
} //同样是做了字节码重组这样一件事情
//对于使用API的用户来说,是无感知
@Override
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { //要干的哪些事情 obj是生成以后的子类的引用 调用子类的引用就会调用这个子 intercept方法 调用super方法
System.out.println("我是GP媒婆:" + "得给你找个异性才行");
System.out.println("开始进行海选...");
System.out.println("------------");
//这个obj的引用是由CGLib给我们new出来的
//cglib new出来以后的对象,是被代理对象的子类(继承了我们自己写的那个类)
//OOP, 在new子类之前,实际上默认先调用了我们super()方法的,
//new了子类的同时,必须先new出来父类,这就相当于是间接的持有了我们父类的引用
//子类重写了父类的所有的方法
//我们改变子类对象的某些属性,是可以间接的操作父类的属性的
proxy.invokeSuper(obj, args); //可以直接调用 调用的是父类哦
System.out.println("------------");
System.out.println("如果合适的话,就准备办事");
return null;
} }

测试类

public class TestGglibProxy {

    public static void main(String[] args) {

        //JDK的动态代理是通过接口来进行强制转换的
//生成以后的代理对象,可以强制转换为接口 //CGLib的动态代理是通过生成一个被代理对象的子类,然后重写父类的方法
//生成以后的对象,可以强制转换为被代理对象(也就是用自己写的类)
//子类引用赋值给父类 try {
YunZhongYu obj = (YunZhongYu)new GPMeipo().getInstance(YunZhongYu.class); //面向接口 对外开放 制定规范 接口就是规范 一般是是字符串 包名 类名 方法名之类的
obj.findLove();
} catch (Exception e) {
e.printStackTrace();
} }
}

代理可以实现 在每一个方法调用之前加一些代码,方法嗲用之后加一些代码

AOP: 事务代理、 日志监听

Service方法  开启一个事务   事务的执行是由我们自己的代码完成的

1、监听到是否有异常,可能需要根据异常的类型来决定这个事务是否好回滚or继续提交?(commit or rollback?)

2、事务要关闭掉

通过动态代理给加了代码

-------------------------------------工厂模式

首先要区分 生产者 消费者     消费者不关心工厂、过程  只关心结果  从工厂取东西哈哈

简单工厂:

定义接口:

//产品接口
//汽车需要满足一定的标准
public interface Car { //规定汽车的品牌
String getName(); }

实现之:

public class Bmw implements Car{

    @Override
public String getName() {
return "BMW";
} }
public class Benz implements Car{

    @Override
public String getName() {
return "Benz";
} }
public class Audi implements Car{

    @Override
public String getName() {
return "Audi";
} }

定义工厂类

import com.gupaoedu.vip.factory.Audi;
import com.gupaoedu.vip.factory.Benz;
import com.gupaoedu.vip.factory.Bmw;
import com.gupaoedu.vip.factory.Car; //对于这个工厂来说(太强大了)
//为什么?
//这个工厂啥都能干(不符合现实)
//编码也是一种艺术(融汇贯通),艺术来源于生活,回归到生活的
public class SimpleFactory { //实现统一管理、专业化管理
//如果没有工厂模式,小作坊,没有执行标准的
//如果买到三无产品(没有标准)
//卫生监督局工作难度会大大减轻 //中国制造(按人家的标准执行)
//中国制造向中国创造改变(技术不是问题了,问题是什么?思维能力)
//码农就是执行标准的人
//系统架构师,就是制定标准的人 //不只做一个技术者,更要做一个思考者 public Car getCar(String name){
if("BMW".equalsIgnoreCase(name)){
//Spring中的工厂模式
//Bean
//BeanFactory(生成Bean)
//单例的Bean
//被代理过的Bean
//最原始的Bean(原型)
//List类型的Bean
//作用域不同的Bean //getBean
//非常的紊乱,维护困难
//解耦(松耦合开发)
return new Bmw();
}else if("Benz".equalsIgnoreCase(name)){
return new Benz();
}else if("Audi".equalsIgnoreCase(name)){
return new Audi();
}else{
System.out.println("这个产品产不出来");
return null;
}
} }

测试类(消费者)

public class SimpleFactoryTest {

    public static void main(String[] args) {

        //这边就是我们的消费者
Car car = new SimpleFactory().getCar("Audi");
System.out.println(car.getName()); } }

接下来是 工厂方法模式

定义工厂接口

实现不同工厂

消费者使用

1、定义工厂接口

import com.gupaoedu.vip.factory.Car;

//工厂接口,就定义了所有工厂的执行标准
public interface Factory { //符合汽车上路标准
//尾气排放标准
//电子设备安全系数
//必须配备安全带、安全气囊
//轮胎的耐磨程度
Car getCar(); }

2、实现这个工厂接口

import com.gupaoedu.vip.factory.Bmw;
import com.gupaoedu.vip.factory.Car; public class BmwFactory implements Factory { @Override
public Car getCar() {
return new Bmw();
} }
import com.gupaoedu.vip.factory.Benz;
import com.gupaoedu.vip.factory.Car; public class BenzFactory implements Factory { @Override
public Car getCar() {
return new Benz();
} }

3、测试类

public class FactoryTest {

    public static void main(String[] args) {

        //工厂方法模式
//各个产品的生产商,都拥有各自的工厂
//生产工艺,生成的高科技程度都是不一样的
Factory factory = new AudiFactory();
System.out.println(factory.getCar()); //需要用户关心,这个产品的生产商
factory = new BmwFactory();
System.out.println(factory.getCar()); //增加的代码的使用复杂度 //抽象工厂模式 } }

改进版的工厂方法模式,抽象工厂模式:

这个不再是 接口了 而是 抽象类

抽象类可以引用自己的方法!

默认的方法

import com.gupaoedu.vip.factory.Car;

public class DefaultFactory extends AbstractFactory {

    private AudiFactory defaultFactory = new AudiFactory();

    public Car getCar() {
return defaultFactory.getCar();
} }

工厂方法

import com.gupaoedu.vip.factory.Car;

public abstract class AbstractFactory {

     protected abstract Car getCar();

     //这段代码就是动态配置的功能
//固定模式的委派
public Car getCar(String name){
if("BMW".equalsIgnoreCase(name)){
return new BmwFactory().getCar();
}else if("Benz".equalsIgnoreCase(name)){
return new BenzFactory().getCar();
}else if("Audi".equalsIgnoreCase(name)){
return new AudiFactory().getCar();
}else{
System.out.println("这个产品产不出来");
return null;
}
} }
import com.gupaoedu.vip.factory.Audi;
import com.gupaoedu.vip.factory.Car; //具体的业务逻辑封装
public class AudiFactory extends AbstractFactory { @Override
public Car getCar() {
return new Audi();
} }
public class BenzFactory extends AbstractFactory {

    @Override
public Car getCar() {
return new Benz();
} }
public class BmwFactory extends AbstractFactory {

    @Override
public Car getCar() {
return new Bmw();
} }

单例模式:

整个系统从启动到终止,自会有一个实例

在应用中遇到功能性冲突的时候,需要用到单例模式

单例模式有7种写 法!!!

1.

1 public class Singleton implements java.io.Serializable {
2 public static Singleton INSTANCE = new Singleton();
3 protected Singleton() { }
4 private Object readResolve() {
5 return INSTANCE;
6 }
7 }

2、

//懒汉式单例类.在第一次调用的时候实例化自己
public class Singleton1 {
//1、第一步先将构造方法私有化
private Singleton1() {}
//2、然后声明一个静态变量保存单例的引用
private static Singleton1 single = null;
//3、通过提供一个静态方法来获得单例的引用
//不安全的
public static Singleton1 getInstance() {
if (single == null) {
single = new Singleton1();
}
return single;
}
}

3、

//懒汉式单例.保证线程安全
public class Singleton2 {
//1、第一步先将构造方法私有化
private Singleton2() {}
//2、然后声明一个静态变量保存单例的引用
private static Singleton2 single=null;
//3、通过提供一个静态方法来获得单例的引用
//为了保证多线程环境下正确访问,给方法加上同步锁synchronized
//慎用 synchronized 关键字,阻塞,性能非常低下的
//加上synchronized关键字以后,对于getInstance()方法来说,它始终单线程来访问
//没有充分利用上我们的计算机资源,造成资源的浪费
public static synchronized Singleton2 getInstance() {
if (single == null) {
single = new Singleton2();
}
return single;
}
}

4、

//懒汉式单例.双重锁检查
public class Singleton3 {
//1、第一步先将构造方法私有化
private Singleton3() {}
//2、然后声明一个静态变量保存单例的引用
private static Singleton3 single=null;
//3、通过提供一个静态方法来获得单例的引用
//为了保证多线程环境下的另一种实现方式,双重锁检查
//性能,第一次的时候
public static Singleton3 getInstance() {
if (single == null) {
synchronized (Singleton3.class) {
if (single == null) {
single = new Singleton3();
}
}
}
return single;
}
}

5、

//懒汉式(静态内部类)
//这种写法,即解决安全问题,又解决了性能问题
//这个代码,没有浪费一个字
public class Singleton4 {
//1、先声明一个静态内部类
//private 私有的保证别人不能修改
//static 保证全局唯一
private static class LazyHolder {
//final 为了防止内部误操作,代理模式,GgLib的代理模式
private static final Singleton4 INSTANCE = new Singleton4();
}
//2、将默认构造方法私有化
private Singleton4 (){}
//相当于有一个默认的public的无参的构造方法,就意味着在代码中随时都可以new出来 //3、同样提供静态方法获取实例
//final 确保别人不能覆盖
public static final Singleton4 getInstance() { //方法中的逻辑,是要在用户调用的时候才开始执行的
//方法中实现逻辑需要分配内存,也是调用时才分配的
return LazyHolder.INSTANCE;
} // static int a = 1;
// //不管该class有没有实例化,static静态块总会在classLoader执行完以后,就加载完毕
// static{
// //静态块中的内容,只能访问静态属性和静态方法
// //只要是静态方法或者属性,直接可以用Class的名字就能点出来
// Singleton4.a = 2;
// //JVM 内存中的静态区,这一块的内容是公共的
// }
} //我们所写的所有的代码,在java的反射机制面前,都是裸奔的
//反射机制是可以拿到private修饰的内容的
//我们可以理解成即使加上private也不靠谱(按正常套路出牌,貌似可以) //类装载到JVM中过程
//1、从上往下(必须声明在前,使用在后)
//先属性、后方法
//先静态、后动态

6、

  //类似Spring里面的方法,将类名注册,下次从里面直接获取。
public class Singleton6 {
private static Map<String,Singleton6> map = new HashMap<String,Singleton6>();
static {
Singleton6 single = new Singleton6();
map.put(single.getClass().getName(), single);
}
//保护的默认构造子
protected Singleton6(){}
//静态工厂方法,返还此类惟一的实例
public static Singleton6 getInstance(String name) {
if(name == null) {
name = Singleton6.class.getName();
}
if(map.get(name) == null) {
try {
map.put(name, (Singleton6) Class.forName(name).newInstance());
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
return map.get(name);
}
}

测试类

public class TestMain {
public static void main(String[] args){
TestSingleton ts1 = TestSingleton.getInstance();
ts1.setName("james");
TestSingleton ts2 = TestSingleton.getInstance();
ts2.setName("tom"); ts1.printInfo();
ts2.printInfo(); if(ts1 == ts2){
System.out.println("创建的是同一个实例" + ts1.getName());
}else{
System.out.println("创建的不是同一个实例" + ts1.getName());
}
}
}
public class TestSingleton {
String name = null;
private TestSingleton() {} //注意这里用到了volatile关键字
private static volatile TestSingleton instance = null; public static TestSingleton getInstance() {
if (instance == null) {
synchronized (TestSingleton.class) {
if (instance == null) {
instance = new TestSingleton();
}
}
}
return instance;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public void printInfo() {
System.out.println("the name is " + name);
} }
public class TestThread {

    public static void main(String[] args) {
//启动100线程同时去抢CPU
int count = 100; //发令枪,测试并发经常用到
CountDownLatch latch = new CountDownLatch(count);
//Set默认去去重的,set是本身线程不安全的
//
final Set<Singleton1> syncSet = Collections.synchronizedSet(new HashSet<Singleton1>()); for (int i = 0; i < count; i++) {
new Thread(){ @Override
public void run() {
syncSet.add(Singleton1.getInstance());
}
}.start(); latch.countDown();
} try {
latch.await();//等待所有线程全部完成,最终输出结果
System.out.println(syncSet.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
} }

委派模式:

1类似中介的功能(委托机制)

2只有被委托人的引用

两个角色 受托人 委托人

定义一个接口

public class Dispatcher implements IExector{
IExector exector; Dispatcher(IExector exector){
this.exector = exector;
} //项目经理,虽然也有执行方法
//但是他的工作职责是不一样的
public void doing() {
this.exector.doing();
} }

两个员工类实现这个接口

public class ExectorA implements IExector {

    @Override
public void doing() {
System.out.println("xxoo");
} }
public class ExectorB implements IExector{

    @Override
public void doing() {
System.out.println("员工B开始执行任务");
} }

项目经理类

public class Dispatcher implements IExector{
IExector exector; Dispatcher(IExector exector){
this.exector = exector;
} //项目经理,虽然也有执行方法
//但是他的工作职责是不一样的
public void doing() {
this.exector.doing();
} }

测试

public class DispatcherTest {

    public static void main(String[] args) {
Dispatcher dispatcher = new Dispatcher(new ExectorA());
//看上去好像是我们的项目经理在干活
//但实际干活的人是普通员工
//这就是典型,干活是我的,功劳是你的
dispatcher.doing();
} }

IOC容器中,有一个Register的东西(为了告诉我们的容器,在这个类被初始化的过程中,需要做很多不同的逻辑处理,需要实现多个任务执行者,分别实现各自的功能 )

关于策略模式,参考系 Comparator方法就可以啦 返回  -1 0 1这种的

a、比较器接口

b、调用时候有自己的实现

//比较器
public interface Comparator { int compareTo(Object obj1,Object obj2); }
public class ObjectComparator implements Comparator{

    @Override
public int compareTo(Object obj1, Object obj2) {
return 0;
} }
public class NumberComparator implements Comparator{

    @Override
public int compareTo(Object obj1, Object obj2) {
return 0;
} }
public class MyList {

    public void sort(Comparator com){
// com.compareTo(obj1, obj2);
System.out.println("执行逻辑");
} }
public class MyListTest {

    public static void main(String[] args) {
//new MyList().sort(new NumberComparator()); //策略模式
// List<Long> numbers = new ArrayList<Long>();
//
// Collections.sort(numbers, new Comparator<Long>() {
//
// @Override
// //返回值是固定的
// //0 、-1 、1
// //0 、 >0 、<0
// public int compare(Long o1, Long o2) {
//
// //中间逻辑是不一样的
//
// return 0;
// }
//
//
// });
}
}

原型模式:

首先要设计个原型

实现 Cloneable接口

public class ConcretePrototype implements Cloneable{

    private int age;

    private String name;

    public ArrayList<String> list = new ArrayList<String>();

    protected Object clone() throws CloneNotSupportedException {
ConcretePrototype prototype = null;
try{
prototype = (ConcretePrototype)super.clone();
prototype.list = (ArrayList)list.clone(); //克隆基于字节码的
//用反射,或者循环
}catch(Exception e){ } return prototype;
} //定义上100个属性 public int getAge() {
return age;
} public void setAge(int age) {
this.age = age;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} }
public class CloneTest {

    public static void main(String[] args) {

        ConcretePrototype cp = new ConcretePrototype();
cp.setAge(18);
cp.setName("Tom"); //cp.list.add("Tom"); try {
ConcretePrototype copy = (ConcretePrototype)cp.clone(); System.out.println(copy.list == cp.list);
System.out.println(copy.getAge() + "," + copy.getName() + copy.list.size());
} catch (CloneNotSupportedException e) {
e.printStackTrace();
} //就是一个现成的对象,这个对象里面有已经设置好的值
//当我要新建一个对象,并且要给新建的对象赋值,而且赋值内容要跟之前的一模一样 //ConcretePrototype cp = new ConcretePrototype();
//cp.setAge(18); //ConcretePrototype copy = new ConcretePrototype();
//copy.setAge(cp.getAge());
//copy.setName(cp.getName());
//用循环,用反射,确实可以的(反射性能并不高)
//字节码复制newInstance() //ConcretePrototype copy = cp;
//ORM的时候经常用到的 //能够直接拷贝其实际内容的数据类型/只支持9种,八大基本数据类型+String 浅拷贝
//深拷贝
} }

原型模式:

//猴子
public class Monkey {
//身高
protected int height;//基本
//体重
protected int weight;
//生日
protected Date birthday;//不是基本类型 public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public int getWeight() {
return weight;
}
public void setWeight(int weight) {
this.weight = weight;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
} }
public class TestPrototype {
public static void main(String[] args) {
TheGreatestSage sage = new TheGreatestSage();
sage.change(); //跟《西游记》中描述的一致,怎么办?
}
}
public class GoldRingedStaff implements Serializable{

    private float height = 100; //长度
private float diameter = 10;//直径 /**
* 金箍棒长大
*/
public void grow(){
this.diameter *= 2;
this.height *= 2;
} /**
* 金箍棒缩小
*/
public void shrink(){
this.diameter /= 2;
this.height /= 2;
} }
/**
* 齐天大圣
*
*/
public class TheGreatestSage extends Monkey implements Cloneable,Serializable{ //金箍棒
private GoldRingedStaff staff; //从石头缝里蹦出来
public TheGreatestSage(){
this.staff = new GoldRingedStaff();
this.birthday = new Date();
this.height = 150;
this.weight = 30;
System.out.println("------------------------");
} //分身技能
public Object clone(){
//深度克隆
ByteArrayOutputStream bos = null;
ObjectOutputStream oos = null;
ByteArrayInputStream bis = null;
ObjectInputStream ois = null;
try {
//return super.clone();//默认浅克隆,只克隆八大基本数据类型和String
//序列化
bos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(bos);
oos.writeObject(this); //反序列化
bis = new ByteArrayInputStream(bos.toByteArray());
ois = new ObjectInputStream(bis);
TheGreatestSage copy = (TheGreatestSage)ois.readObject();
copy.birthday = new Date(); return copy;
} catch (Exception e) {
e.printStackTrace();
return null;
}finally{
try {
bos.close();
oos.close();
bis.close();
ois.close(); } catch (IOException e) {
e.printStackTrace();
}
}
} //变化
public void change(){
TheGreatestSage copySage = (TheGreatestSage)clone();
System.out.println("大圣本尊生日是:" + this.getBirthday().getTime());
System.out.println("克隆大圣的生日是:" + copySage.getBirthday().getTime());
System.out.println("大圣本尊和克隆大圣是否为同一个对象:" + (this == copySage));
System.out.println("大圣本尊持有的金箍棒跟克隆大圣持有金箍棒是否为同一个对象:" + (this.getStaff() == copySage.getStaff()));
} public GoldRingedStaff getStaff() {
return staff;
} public void setStaff(GoldRingedStaff staff) {
this.staff = staff;
} }

模板模式:

模板(固定的执行流程)

定义冲饮料的机器:

//冲饮料(拿出去卖钱了)
public abstract class Bevegrage { //不能被重写
public final void create(){
//1、把水烧开
boilWater();
//2、把杯子准备好、原材料放到杯中
pourInCup();
//3、用水冲泡
brew();
//4、添加辅料
addCoundiments();
} public abstract void pourInCup(); public abstract void addCoundiments(); public void brew(){
System.out.println("将开水放入杯中进行冲泡");
}; public void boilWater(){
System.out.println("烧开水,烧到100度可以起锅了");
} }

实现为冲咖啡的

public class Coffee  extends Bevegrage{

    //原材料放到杯中
public void pourInCup() {
System.out.println("将咖啡倒入杯中");
} //房辅料
public void addCoundiments() {
System.out.println("添加牛奶和糖");
} }

实现为泡茶的

public class Tea extends Bevegrage{

    //原材料放到杯中
public void pourInCup() {
System.out.println("将茶叶放入杯中");
} //房辅料
public void addCoundiments() {
System.out.println("添加蜂蜜");
} }

测试类

public class TestTemplate {

    public static void main(String[] args) {

//        Coffee coffee = new Coffee();
// coffee.create(); Tea tea = new Tea();
tea.create(); } //SpringJDBC
//是java规范,各个数据库厂商自己去实现
//1、加载驱动类DriverManager
//2、建立连接
//3、创建语句集(标准语句集、预处理语句集)(语句集? MySQL、Oracle、SQLServer、Access)
//4、执行语句集
//5、结果集ResultSet 游标
//ORM(?) }

Spring JDBC就是个模板模式

是 Java的规范  各个数据库厂商去实现

1、加载驱动类 DriverManager

2、建立连接

3、创建语句集(标准语句集、预处理语句集)(语句集合? Mysql oracle sqlserver access 语句不太一样哦)

4、执行语句集

5、结果集ResultSet 游标

ORM (连接的是哪个对象 映射哪个结果 List or 自定义的类 还是??运行时候才知道)

https://www.cnblogs.com/toov5/p/9472082.html

Spring源码分析 之浅谈设计模式的更多相关文章

  1. mybatis缓存源码分析之浅谈缓存设计

    本文是关于mybatis缓存模块设计的读后感,关于缓存的思考,关于mybatis的缓存源码详细分析在另一篇文章:https://www.cnblogs.com/gmt-hao/p/12448896.h ...

  2. 【JDK源码分析】浅谈HashMap的原理

    这篇文章给出了这样的一道面试题: 在 HashMap 中存放的一系列键值对,其中键为某个我们自定义的类型.放入 HashMap 后,我们在外部把某一个 key 的属性进行更改,然后我们再用这个 key ...

  3. Spring 源码分析之 bean 依赖注入原理(注入属性)

         最近在研究Spring bean 生命周期相关知识点以及源码,所以打算写一篇 Spring bean生命周期相关的文章,但是整理过程中发现涉及的点太多而且又很复杂,很难在一篇文章中把Spri ...

  4. Spring源码分析——BeanFactory体系之抽象类、类分析(一)

    上一篇介绍了BeanFactory体系的所有接口——Spring源码分析——BeanFactory体系之接口详细分析,本篇就接着介绍BeanFactory体系的抽象类和接口. 一.BeanFactor ...

  5. spring源码分析(二)Aop

    创建日期:2016.08.19 修改日期:2016.08.20-2016.08.21 交流QQ:992591601 参考资料:<spring源码深度解析>.<spring技术内幕&g ...

  6. 框架-spring源码分析(一)

    框架-spring源码分析(一) 参考: https://www.cnblogs.com/heavenyes/p/3933642.html http://www.cnblogs.com/BINGJJF ...

  7. Spring源码分析之IOC的三种常见用法及源码实现(二)

    Spring源码分析之IOC的三种常见用法及源码实现(二) 回顾上文 我们研究的是 AnnotationConfigApplicationContext annotationConfigApplica ...

  8. spring源码分析之spring-core总结篇

    1.spring-core概览 spring-core是spring框架的基石,它为spring框架提供了基础的支持. spring-core从源码上看,分为6个package,分别是asm,cgli ...

  9. Spring源码分析——BeanFactory体系之抽象类、类分析(二)

    上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之 ...

随机推荐

  1. codeforces 1037

    题解: E-trips 哎哎哎好傻逼啊 没有想到算不能的一直在想怎么算能的 太傻逼了 其实很简单 我们只需要对好友<=k的首先dfs一下给他连接着的朋友-1 然后如果小于了就递归下去 这个正确性 ...

  2. C# 之 GUID格式化

    Guid的带参数的ToString()方法来实现格式化,如下: //// 摘要: //     根据所提供的格式说明符,返回此 System.Guid 实例值的字符串表示形式. //// 参数: // ...

  3. IOS内存约定-【ios】

    IOS中内存采用引用计数的方式,在释放内存编程时采用约定的方式,在这里不长篇大论具体内存的原理,只从实用角度出发记录下如何根据这些约定来释放内存. 具体约定为: 当你使用new.alloc.copy  ...

  4. POJ2676 Sudoku 舞蹈链 DLX

    欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目(传送门) 题意概括 给出一个残缺的数独,求解.SPJ 题解 DLX + 矩阵构建  (两个传送门) 代码 #includ ...

  5. 001 Hello Security 的框架搭建

    一:STS 1.下载STS 官网:http://spring.io/tools 使用一个干净的STS进行操作学习. 2.jdk检查 3.添加自己的maven 4.使用tomcat 二:新建项目 1.新 ...

  6. 054 kafka内部机制

    一:数据格式与数据存储 1.总结 存储在磁盘文件中(index+log) 顺序读写的 基于offset偏移量来管理数据的(主要是读操作) 由分区器根据key值决定数据分布到哪个分区,默认使用hash ...

  7. 004 Java的一次面试题,学长列举

    据说是Java的面试题,感觉有些汗颜,所以决定研究一下. 1.线程.进程.协程的区别,他们怎么进行线程的交互? 2.k8s内的scheduler怎么做的,流程?跟etcd怎么交互? 3.hashmap ...

  8. tp5的路由

    路由模式:普通.强制和混合 普通模式: //配置文件关闭路由,完全使用默认的PATH_INFO方式URL 'url_route_on' => false, 关闭路由后的普通模式任然可以通过操作方 ...

  9. HBase表的基本结构和常用命令行操作

    一.HBase表的基本结构 1.概述: 平时常见的MySQL.Oracle数据库都是传统型关系数据库,它们都是按行查询.按行存储:而HBase为非关系型数据库,它是按列存储的的. 在HBase插入数据 ...

  10. JavaEE 之 Mybatis

    1.Mybatis a.定义:MyBatis 是支持普通 SQL查询,存储过程和高级映射的优秀持久层框架 b.步骤: ①在src下创建 SqlMapConfig.xml 及 datasource.pr ...