Spring 的核心功能是 IOC 容器以及 AOP 面向切面编程,同样也引入很多设计模式,提高代码的扩展性和灵活性。
Spring 中的 BeanFactory 就是简单工厂模式的体现,BeanFactory 是 Spring IOC 容器中的一个核心接口,
public interface BeanFactory { Object getBean(String name) throws BeansException; <T> T getBean(String name, Class<T> requiredType); Object getBean(String name, Object... args); <T> T getBean(Class<T> requiredType); <T> T getBean(Class<T> requiredType, Object... args);}
通过工厂类的方法 getBean 来获取对象实例,这是典型的简单工厂模式,只不过 Spring 是用反射机制来创建 Bean 的。
在简单工厂中,由工厂类进行所有的逻辑判断、实例创建;如果不想在工厂类中进行判断,可以为不同的产品提供不同的工厂,不同的工厂生产不同的产品,每一个工厂都只对应一个相应的对象,这就是工厂方法模式。
public interface FactoryBean<T> { T getObject(); Class<?> getObjectType(); boolean isSingleton();}
定义一个类 UserFactoryBean 来实现 FactoryBean 接口,主要是在 getObject 方法里 new 一个 User 对象。这样我们通过 getBean(id) 获得的是该工厂所产生的 User 的实例,而不是 UserFactoryBean 本身的实例,像下面这样:
BeanFactory bf = new ClassPathXmlApplicationContext("user.xml");User userBean = (User) bf.getBean("userFactoryBean");
单例模式是指一个类在整个系统运行过程中,只允许产生一个实例。在 Spring 中,Bean 可以被定义为两种模式:prototype(多例)和 singleton(单例),Spring Bean 默认是单例模式
如何实现?
public class DefaultSingletonBeanRegistry {
// 使用了线程安全容器 ConcurrentHashMap,保存各种单实例对象 private final Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>;
protected Object getSingleton(String beanName) { // 先到 HashMap 中拿 Object Object singletonObject = singletonObjects.get(beanName);
// 如果没拿到通过反射创建一个对象实例,并添加到 HashMap 中 if (singletonObject == null) { singletonObjects.put(beanName, Class.forName(beanName).newInstance()); }
// 返回对象实例 return singletonObjects.get(beanName); }}
所谓代理,是指代理类与目标类实现了相同的接口,客户端必须通过代理才能与目标类进行交互
•抽象接口:定义目标类及代理类的共同接口,这样在任何可以使用目标对象的地方都可以使用代理对象。•目标对象:定义了代理对象所代表的目标对象,专注于业务功能的实现。•代理对象:代理对象内部含有目标对象的引用,收到客户端的调用请求时,代理对象通常不会直接调用目标对象的方法,而是在调用之前和之后实现一些额外的逻辑。
代理模式的好处是,可以在目标对象业务功能的基础上添加一些公共的逻辑,比如我们想给目标对象加入日志、权限管理和事务控制等功能,我们就可以使用代理类来完成,而没必要修改目标类,从而使得目标类保持稳定。这其实是开闭原则的体现,不要随意去修改别人已经写好的代码或者方法。
静态代理,在程序运行之前就已经编译完成。
动态代理,代理类并不是在 Java 代码中定义的,而是在运行时根据我们在 Java 代码中的“指示”动态生成的。
Java 的java.lang.reflect包里提供了一个 Proxy 类和一个 InvocationHandler 接口,通过这个类和这个接口可以生成动态代理对象。
相比于静态代理,动态代理的优势在于可以很方便地对代理类的方法进行统一的处理,而不用修改代理类中的每个方法。