编写我们待测试的Bean类 SpringBean.java
package com.powernode.spring6.bean;/*** @author Bonbons* @version 1.0*/
public class SpringBean {public SpringBean(){System.out.println("调用了无参构造方法");}
}
我们之前就知道,Spring创建对象是在初始化上下文的时候进行的,而且调用了无参构造方法,此处我们直接给出无参构造方法,方便更好的说明问题
编写我们的 spring 配置文件 spring-scope.xml
编写测试方法,利用getBean方法多次获取我们的Bean对象
@Testpublic void testBeanScope(){ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");SpringBean sb = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb);SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb2);SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb3);/*** 测试结果,输出的三个bean是一个对象* 原因:* 在我们解析XML配置文件的时候,对象就已经调用无参构造方法创建结束了* 在我们调用getBean的时候得到的就是已经创建好的对象,默认情况下是单例模式的*/}
我们可以发现,调用了三次无参构造方法,我们获得的是三个不同的Bean的对象
我们在使用默认的作用域时,无论是否调用getBean方法,都会调用我们Bean类的无参构造方法,但是当我们将作用域定义为 prototype 的时候,如果没有调用getBean方法就不会去调用无参构造方法
其实我们Bean 的作用域并不是只有两个,但是有些作用域只有在特定的情景下才会有效
那么Bean的作用域都包括哪些呢?

尽管自定义的 scope 很少使用,但是我们还是给出如果来自定义 scope?
需求:我们先测试一下,不同线程创建的Bean是单例的还是多列的?
还是利用我们上面的文件,只是在测试方法处创建新的线程进而再获得实例 【scope采用默认值】
@Testpublic void testThreadScope(){// 获得一个SpringBean的实例ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb1);SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb2);// 创建一个新的线程new Thread(new Runnable() {@Overridepublic void run() {SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb3);}}).start();}
经过前面在 singleton 部分的测试我们知道,sb1和sb2一定是同一个对象,那么到底不同线程的bean是单例的还是多例的呢?

(1)我们自定义一个Scope类,实现Scope接口
(2)将我们自定义的Scope注册到Spring容器中 【此处我们直接就定义到了上面的 spring-scope.xml中】
(3)想要使用我们的这个scope只需在声明bean的时候将scope属性的值设置为我们自定义的scope即可
(4)再次测试我们上面那个不同线程获得的bean对象是否为同一个
@Testpublic void testThreadScope(){// 获得一个SpringBean的实例ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-scope.xml");SpringBean sb1 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb1);SpringBean sb2 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb2);// 创建一个新的线程new Thread(new Runnable() {@Overridepublic void run() {SpringBean sb3 = applicationContext.getBean("sb", SpringBean.class);System.out.println(sb3);}}).start();}

通过结果我们可以看到,已经实现了不同线程通过getBean方法获得的bean的对象不是同一个
GoF 的中文含义代表四人组(指的是编写设计模式的四个作者)
设计模式:可以重复利用的一种解决问题的方案,该书中包含 23 种设计模式,当然也存在其他的设计模式
GoF 23种设计模式可以分为三大类:
因为Spring容器使用了大量的工厂模式,所以接下来我们对工厂模式展开论述
编写抽象产品角色,抽象类 + 抽象方法 Weapon.java
package com.powernode.simple.factory;/*** 抽象产品角色* @author Bonbons* @version 1.0*/
public abstract class Weapon {// 定义一个抽象的攻击方法,具体内容由其子类去实现public abstract void attack();
}
编写具体产品角色,此处我们就给两个 Tank.java、Dagger.java 要继承我们的抽象产品角色并实现抽象方法
package com.powernode.simple.factory;/*** 具体产品角色* @author Bonbons* @version 1.0*/
public class Tank extends Weapon{@Overridepublic void attack() {System.out.println("向我开炮!!!");}
}
package com.powernode.simple.factory;/*** 具体产品角色* @author Bonbons* @version 1.0*/
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("偷袭!!!");}
}
编写工厂类角色,WeaponFactory 类提供一个静态方法,根据我们客户端传递的参数,来决定生成哪个具体的产品角色对象
package com.powernode.simple.factory;/*** 工厂类角色* @author Bonbons* @version 1.0*/
public class WeaponFactory {/*** 简单工厂模式我们又称之为静态工厂模式:* 通过一个静态方法,根据我们的参数生成对应的具体产品角色的对象*/public static Weapon get(String weapon){// 通过if条件判断去匹配对应的角色if("TANK".equals(weapon)){return new Tank();}else if("FIGHTER".equals(weapon)){return new Fighter();}else if("DAGGER".equals(weapon)){return new Dagger();}else{throw new RuntimeException("无法识别该类型!!!");}}
}
编写Test测试方法:
package com.powernode.simple.factory;/*** @author Bonbons* @version 1.0*/
public class Test {public static void main(String[] args) {// 如果我们需要坦克Weapon tank = WeaponFactory.get("TANK");tank.attack();// 如果我们需要偷袭Weapon dagger = WeaponFactory.get("DAGGER");dagger.attack();}
}

Spring 中的BeanFactory就采用了简单工厂模式
简单工厂模式的优点:
简单工厂模式的缺点:
创建一个新模块 factory-method 并不需要添加依赖什么的,因为这部分的内容用不到
编写我们的抽象产品角色 >> Weapon
package com.powernode.factory.method;/*** 抽象产品角色* @author Bonbons* @version 1.0*/
abstract public class Weapon {public abstract void attack();
}
编写我们的具体产品角色 >> Gun、Dagger
package com.powernode.factory.method;/*** 具体产品角色* @author Bonbons* @version 1.0*/
public class Gun extends Weapon{@Overridepublic void attack() {System.out.println("开枪射击!!!");}
}
package com.powernode.factory.method;/*** 具体产品角色* @author Bonbons* @version 1.0*/
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("给你一刀!!!");}
}
编写我们的抽象工厂 >> WeaponFactory
package com.powernode.factory.method;/*** 抽象工厂角色* @author Bonbons* @version 1.0*/
abstract public class WeaponFactory {// 给出获得工厂对象的get方法,具体获得哪个工厂的对象由实现它的工厂决定public abstract Weapon get();
}
编写我们的具体工厂角色 >> GunFactory、DaggerFactory
package com.powernode.factory.method;/*** 具体工厂角色* @author Bonbons* @version 1.0*/
public class GunFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Gun();}
}
package com.powernode.factory.method;/*** 具体工厂角色* @author Bonbons* @version 1.0*/
public class DaggerFactory extends WeaponFactory{@Overridepublic Weapon get() {return new Dagger();}
}
编写我们的测试方法
package com.powernode.factory.method;/*** @author Bonbons* @version 1.0*/
public class Test {public static void main(String[] args) {// 我们先获得想要的工厂WeaponFactory daggerFactory = new DaggerFactory();// 调用工厂的get方法,就可以获得对应工厂的产品Weapon dagger = daggerFactory.get();// 然后我们调用我们产品的方法dagger.attack();WeaponFactory gunFactory = new GunFactory();Weapon gun = gunFactory.get();gun.attack();}
}

工厂方法模式的优点:
工厂方法模式的缺点:
如何理解抽象工厂模式?
抽象工厂模式的组成:
需求:我们写一个案例,包含两个系列——武器系列和水果系列
编写武器产品系列: 一个抽象产品角色、两个具体产品角色
package com.powernode.product;/*** 武器产品族* @author 动力节点* @version 1.0* @className Weapon* @since 1.0**/
public abstract class Weapon {public abstract void attack();
}
package com.powernode.product;/*** 武器产品族中的产品等级1* @author 动力节点* @version 1.0* @className Gun* @since 1.0**/
public class Gun extends Weapon{@Overridepublic void attack() {System.out.println("开枪射击!");}
}
package com.powernode.product;/*** 武器产品族中的产品等级2* @author 动力节点* @version 1.0* @className Dagger* @since 1.0**/
public class Dagger extends Weapon{@Overridepublic void attack() {System.out.println("砍丫的!");}
}
编写水果产品系列: 一个抽象产品角色、两个具体产品角色
package com.powernode.product;/*** 水果产品族* @author 动力节点* @version 1.0* @className Fruit* @since 1.0**/
public abstract class Fruit {/*** 所有果实都有一个成熟周期。*/public abstract void ripeCycle();
}
package com.powernode.product;/*** 水果产品族中的产品等级1* @author 动力节点* @version 1.0* @className Orange* @since 1.0**/
public class Orange extends Fruit{@Overridepublic void ripeCycle() {System.out.println("橘子的成熟周期是10个月");}
}
package com.powernode.product;/*** 水果产品族中的产品等级2* @author 动力节点* @version 1.0* @className Apple* @since 1.0**/
public class Apple extends Fruit{@Overridepublic void ripeCycle() {System.out.println("苹果的成熟周期是8个月");}
}
编写我们的抽象工厂角色
package com.powernode.factory;import com.powernode.product.Fruit;
import com.powernode.product.Weapon;/*** 抽象工厂* @author 动力节点* @version 1.0* @className AbstractFactory* @since 1.0**/
public abstract class AbstractFactory {public abstract Weapon getWeapon(String type);public abstract Fruit getFruit(String type);
}
编写我们的具体工厂角色 >> 采用简单工厂的方式实现的
package com.powernode.factory;import com.powernode.product.Dagger;
import com.powernode.product.Fruit;
import com.powernode.product.Gun;
import com.powernode.product.Weapon;/*** 武器族工厂* @author 动力节点* @version 1.0* @className WeaponFactory* @since 1.0**/
public class WeaponFactory extends AbstractFactory{public Weapon getWeapon(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Gun".equals(type)) {return new Gun();} else if ("Dagger".equals(type)) {return new Dagger();} else {throw new RuntimeException("无法生产该武器");}}@Overridepublic Fruit getFruit(String type) {return null;}
}
package com.powernode.factory;import com.powernode.product.*;/*** 水果族工厂* @author 动力节点* @version 1.0* @className FruitFactory* @since 1.0**/
public class FruitFactory extends AbstractFactory{@Overridepublic Weapon getWeapon(String type) {return null;}public Fruit getFruit(String type){if (type == null || type.trim().length() == 0) {return null;}if ("Orange".equals(type)) {return new Orange();} else if ("Apple".equals(type)) {return new Apple();} else {throw new RuntimeException("我家果园不产这种水果");}}
}
编写我们的客户端测试程序:
package com.powernode.client;import com.powernode.factory.AbstractFactory;
import com.powernode.factory.FruitFactory;
import com.powernode.factory.WeaponFactory;
import com.powernode.product.Fruit;
import com.powernode.product.Weapon;/*** @author 动力节点* @version 1.0* @className Client* @since 1.0**/
public class Client {public static void main(String[] args) {// 客户端调用方法时只面向AbstractFactory调用方法。AbstractFactory factory = new WeaponFactory(); // 注意:这里的new WeaponFactory()可以采用 简单工厂模式 进行隐藏。Weapon gun = factory.getWeapon("Gun");Weapon dagger = factory.getWeapon("Dagger");gun.attack();dagger.attack();AbstractFactory factory1 = new FruitFactory(); // 注意:这里的new FruitFactory()可以采用 简单工厂模式 进行隐藏。Fruit orange = factory1.getFruit("Orange");Fruit apple = factory1.getFruit("Apple");orange.ripeCycle();apple.ripeCycle();}
}
抽象工厂模式的优缺点:
上一篇:网络安全设备之防火墙技术详解
下一篇:不要脸的你擦擦,然后享受盛宴