DI依赖注入的进阶

首先写接口类:

package com.action;
public interface HelloApi {
	void sayHello();
}

其次写实现类:
package com.action;
public class HelloApiImpl implements HelloApi{
	private String message;
	private int index;
	public HelloApiImpl(String message,int index){
		this.message = message;
		this.index = index;
	}
	@Override
	public void sayHello() {
		System.out.println(index+" : "+message);
	}
}

第一阶段:通过构造方法注入的各种方式

第一,配置xml文件,从下面开始的每一个xml文件都省略掉beans了。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" class="com.action.HelloApiImpl">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" class="com.action.HelloApiImpl">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" class="com.action.HelloApiImpl">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
</beans>

第二:写测试类。
package com.action;

import org.springframework.beans.factory.beanfactory;
import org.springframework.context.support.ClasspathXmlApplicationContext;

public class DependencyInjectTest {
	public static void main(String[] args) {
		beanfactory beanfactory = new ClasspathXmlApplicationContext("com/resource/ConstructorDependencyInject.xml");
		HelloApi byIndex = beanfactory.getBean("byIndex",HelloApi.class);
		byIndex.sayHello();
		HelloApi byType = beanfactory.getBean("byType",HelloApi.class);
		byType.sayHello();
		HelloApi byName = beanfactory.getBean("byName",HelloApi.class);
		byName.sayHello();
		/*通过参数名称依赖注入的时候,需要开启调试模式。以下为比较正式的解释:
		 * 构造器注入可以根据参数索引注入、参数类型注入或Spring3支持的参数名注入,但参数名注入是有限制的,
		 * 需要使用在编译程序时打开调试模式(即在编译时使用“javac –g:vars”在class文件生成变量调试信息,
		 * 认是不包含变量调试信息的,从而能获取参数名字,否则获取不到参数名字)
		 * 或在构造器上使用@ConstructorProperties(java.beans.ConstructorProperties)注解来指定参数名。
		 * 
		 * 通过构造器参数名字注入方式,先确保编译时class文件包含“变量信息”
		 * 在myeclipse中的调整步骤为:进入项目属性,java compiler,下面add varible……勾选上。
		 * */
	}
}

第三,静态工厂类和实例工厂类(测试类省略)

静态工厂

package com.action;
public class DependencyInjectByFactory {
	//静态工厂类
	private static HelloApi newInstance(String message,int index){
		return new HelloApiImpl(message,index);
	}
}
xml文件
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" class="com.action.DependencyInjectByFactory" factory-method="newInstance">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
实例工厂
package com.action;
public class DependencyByInstanceFactory {
	//实例工厂类
	public HelloApi newInstance(String message,index);
	}
}
xml文件
	
	<bean id="DependencyByInstanceFactory" class="com.action.DependencyByInstanceFactory"></bean>
	
	<!-- 通过构造器参数索引方式依赖注入 -->
	<bean id="byIndex" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg index="0" value="Hello Spring byIndex..."></constructor-arg>
		<constructor-arg index="1" value="1"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数数据类型方式依赖注入 -->
	<bean id="byType" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg type="java.lang.String" value="Hello Spring byType..."></constructor-arg>
		<constructor-arg type="int" value="2"></constructor-arg>
	</bean>
	
	<!-- 通过构造器参数名称方式依赖注入 -->
	<bean id="byName" factory-bean="DependencyByInstanceFactory" factory-method="newInstance">
		<constructor-arg name="message" value="Hello Spring byName..."></constructor-arg>
		<constructor-arg name="index" value="3"></constructor-arg>
	</bean>
这个时候所有的不同,各种方法的各种优势都展现出来了。

对于setter注入的初步了解,测试类省略。

实现类

package com.action;
public class HelloApiSet implements HelloApi{
	private String message;
	private int index;
	public void setMessage(String message) {
		this.message = message;
	}
	public void setIndex(int index) {
		this.index = index;
	}
	public void sayHello(){
		System.out.println(index+" : "+message);
	}
}
xml
	<bean id="bean" class="com.action.HelloApiSet">
		<property name="message" value="Hello TestSet"></property>
		<property name="index" value="123"></property>
	</bean>

常量注入

		<property name="index" value="123"></property>
		<property name="index"><value>123</value></property>
第一种和第二种是表述方式是一样的,第二种中的123是以字符串形式传入的,由spring自动转换成需要的类型,如果转换错误会抛出相应的异常。

Spring类型转换系统对于boolean类型进行了容错处理,除了可以使用“true/false”标准的Java值进行注入,还能使用“yes/no”、“on/off”、“1/0”来代表“对/错”。

先写类。

package com.action;
public class BooleanBean {
	private boolean success;
	public void setSuccess(boolean success){
		this.success = success;
	}
	public void isSuccess(){
		System.out.println(success);
	}
}
xml
	<!-- true/false 以下都是按“对/错”的位置排列的-->
	<bean id="bean1" class="com.action.BooleanBean">
		<property name="success" value="true"></property>
	</bean>
	<!-- yes/no -->
	<bean id="bean2" class="com.action.BooleanBean">
		<property name="success" value="yes"></property>
	</bean>
	<!-- on/off -->
	<bean id="bean3" class="com.action.BooleanBean">
		<property name="success" value="on"></property>
	</bean>
	<!-- 1/0 -->
	<bean id="bean4" class="com.action.BooleanBean">
		<property name="success" value="1"></property>
	</bean>
测试类省略。
集合注入
先测试List,写类
package com.action;
import java.util.List;
public class ListBean {
	private List<String> values;

	public List<String> getValues() {
		return values;
	}

	public void setValues(List<String> values) {
		this.values = values;
	}
	
}
配位文件xml
	<bean name="ListBean" class="com.action.ListBean">
		<property name="values">
			<list>
				<value>1</value>
				<value>2</value>
				<value>3</value>
			</list>
		</property>
	</bean>
测试类
package com.action;
import org.springframework.beans.factory.beanfactory;
import org.springframework.context.support.ClasspathXmlApplicationContext;

public class TestListBean {
	public static void main(String[] args) {
		beanfactory beanfactory = new ClasspathXmlApplicationContext("com/resource/ListInject.xml");
		ListBean listBean = beanfactory.getBean("ListBean",ListBean.class);
		System.out.println(listBean.getValues().size());
//		for (Iterator<String> iterator = listBean.getValues().iterator(); iterator.hasNext();) {
//			String type = (String) iterator.next();
//			System.out.println(type);
//		}
	}
}
当注入Set的时候大致如此,xml文件里面的list改写成Set。数组的时候改成array, 二维数组的话array里面可以还有array。最后说map,map的时候需要指定一些东西。
	<bean name="MapBean" class="com.action.MapBean">
	<property name="values">
		<map key-type="java.lang.String" value-type="java.lang.String">
			<entry>
				<key><value>aaa</value></key>
				<value>bbb</value>
			</entry>
			<entry key="ccc" value="ddd"></entry>
		</map>
		</property>
	</bean>

public class MapBean {
	private Map<String,String> values;

	public Map<String,String> getValues() {
		return values;
	}

	public void setValues(Map<String,String> values) {
		this.values = values;
	}
	
}

public class TestMapBean {
	public static void main(String[] args) {
		beanfactory beanfactory = new ClasspathXmlApplicationContext("com/resource/ListInject.xml");
		MapBean mapBean = beanfactory.getBean("MapBean",MapBean.class);
		for (Iterator<Map.Entry<String,String>> iterator = mapBean.getValues().entrySet().iterator(); iterator.hasNext();) {
			Map.Entry<String,String> temp =  iterator.next();
			System.out.println(temp.getKey()+"==="+temp.getValue());
		}
	}
}

引用其他Bean
package com.action;
public class HelloImpl implements HelloApi{

	@Override
	public void sayHello() {
		System.out.println("I love you,Spring!");
	}
}

package com.action;

public class DecoratorHelloApi implements HelloApi {
	private HelloApi helloApi1;
	//无参
	public DecoratorHelloApi() {
	}
	//有参
	public DecoratorHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	//setter方法
	public void setHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	
	@Override
	public void sayHello() {
		System.out.println("===========装饰一下=============");
		helloApi1.sayHello();
		System.out.println("===========装饰一下=============");
	}

}

	<!-- 定义依赖bean -->
	<bean id="helloImpl" class="com.action.HelloImpl"></bean>
	
	
	<!-- 下面两种方式注入都可以分为三小种,类型,索引和名字 -->
	
	<!-- 通过构造器注入 -->
	<bean id="bean1" class="com.action.DecoratorHelloApi">
		<constructor-arg index="0" ref="helloImpl"></constructor-arg>
	</bean>
	<!-- 通过setter注入 -->
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<property name="helloApi"><!-- 注意最好属性名和依赖bean的名字别一样,妈的我找错找了很久 -->
			<ref bean="helloImpl"/>
		</property>
	</bean>

<ref local>和<ref parent>的配置。(这个有点乱……)

package com.action;
public class HelloImpl implements HelloApi{
	
	private String message;
	private String name;
	
	public HelloImpl() {
	}

	public HelloImpl(String message,String name) {
		this.name = name;
		this.message = message;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getMessage() {
		return message;
	}

	public void setMessage(String message) {
		this.message = message;
	}

	@Override
	public void sayHello() {
		System.out.println(message+"==="+name);
	}
}

package com.action;

import com.action.HelloApi;

public class DecoratorHelloApi implements HelloApi {
	private HelloApi helloApi1;
	//无参
	public DecoratorHelloApi() {
	}
	//有参
	public DecoratorHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	//setter方法
	public void setHelloApi(HelloApi helloApi) {
		this.helloApi1 = helloApi;
	}
	
	@Override
	public void sayHello() {
		System.out.println("===========装饰一下=============");
		helloApi1.sayHello();
		System.out.println("===========装饰一下=============");
	}

}

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<bean id="helloApi" class="com.action.HelloImpl">
		<property name="message" value="Hello"></property>
		<property name="name" value="parent"></property>
	</bean>
</beans>

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context-3.0.xsd">
	
	<bean id="helloApi" class="com.action.HelloImpl">
		<property name="message" value="Hello"></property>
		<property name="name" value="local"></property>
	</bean>
	<!-- 通过parent注入 -->
	<bean id="bean1" class="com.action.DecoratorHelloApi">
		<constructor-arg index="0">
			<ref parent="helloApi" ></ref>
		</constructor-arg>
	</bean>
	
	<!-- 通过local注入 -->
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<!-- <property name="helloApi" ref="helloApi"></property> -->
		<!-- 认情况下是先查当前 -->
		<property name="helloApi">
			<ref local="helloApi" />
		</property>
	</bean>
		
</beans>

package com.action;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClasspathXmlApplicationContext;

public class TestLocalAndparentBeanInject {
	public static void main(String[] args) {
		//初始化父容器
		ApplicationContext parentContext = new ClasspathXmlApplicationContext("com/resource/parentBeanInject.xml");
		//初始化当前容器  应该是这句话定义父子关系的
		ApplicationContext beanContext = new ClasspathXmlApplicationContext(new String[]{"com/resource/localBeanInject.xml"},parentContext);
		HelloApi helloApi1 = beanContext.getBean("bean1",HelloApi.class);
		helloApi1.sayHello();//该helloApi引用parent
		HelloApi helloApi2 = beanContext.getBean("bean2",HelloApi.class);
		helloApi2.sayHello();//该helloApi2引用local
	}
}

定义内部bean
内部Bean就是在<property>或<constructor-arg>内通过<bean>标签定义的Bean,该Bean不管是否指定id或name,该Bean都会有唯一的匿名标识符,而且不能指定别名,该内部Bean对其他外部Bean不可见。
package com.action;
public class HelloImpl implements HelloApi {
      @Override
      public void sayHello() {
             System.out.println("Hello World!");
      }
}

package com.action;
public class HelloApiDecorator implements HelloApi {
private HelloApi helloApi;
//空参构造器
    public HelloApiDecorator() {
}
//有参构造器
    public HelloApiDecorator(HelloApi helloApi) {
        this.helloApi = helloApi;
}  
public void setHelloApi(HelloApi helloApi) {
        this.helloApi = helloApi;
    }
    @Override
    public void sayHello() {
        System.out.println("==========装饰一下===========");
        helloApi.sayHello();
        System.out.println("==========装饰一下===========");
    }
}

	<bean id="bean" class="com.action.HelloApiDecorator">
		<property name="helloApi">
			<bean id="helloApi" class="com.action.HelloImpl"></bean>
		</property>
	</bean>

public class TestInnerBeanInject {
	public static void main(String[] args) {
		ApplicationContext ac = new ClasspathXmlApplicationContext("com/resource/innerBeanInject.xml");
		HelloApi ha = ac.getBean("bean",HelloApi.class);
		ha.sayHello();
		
	}
}

注入null值 可以通过类似方式注入
	<bean id="bean2" class="com.action.DecoratorHelloApi">
		<property name="message"><null/></property>
	</bean>

对象图导航注入支持(这个应该意义不大,我另写一篇吧,把这个完结了。)

配置简写

(以下为转载。)

一、构造器注入:

1)常量值

简写:<constructor-arg index="0" value="常量"/>

全写:<constructor-arg index="0"><value>常量</value></constructor-arg>

2)引用

简写:<constructor-arg index="0" ref="引用"/>

全写:<constructor-arg index="0"><ref bean="引用"/></constructor-arg>

二、setter注入:

1)常量值

简写:<property name="message" value="常量"/>

全写:<property name="message"><value>常量</value></ property>

2)引用

简写:<property name="message" ref="引用"/>

全写:<property name="message"><ref bean="引用"/></ property>

3)数组:<array>没有简写形式

4)列表:<list>没有简写形式

5)集合:<set>没有简写形式

6)字典

简写:<map>

<entry key="键常量" value="值常量"/>

<entry key-ref="键引用" value-ref="值引用"/>

</map>

全写:<map>

<entry><key><value>键常量</value></key><value>值常量</value></entry>

<entry><key><ref bean="键引用"/></key><ref bean="值引用"/></entry>

</map>

7)Properties:没有简写形式

三、使用p命名空间简化setter注入:

使用p命名空间来简化setter注入,具体使用如下:

java代码
  1. <?xmlversion="1.0"encoding="UTF-8"?>
  2. <beansxmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:p="http://www.springframework.org/schema/p"
  5. xsi:schemaLocation="
  6. http://www.springframework.org/schema/beans
  7. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
  8. <beanid="bean1"class="java.lang.String">
  9. <constructor-argindex="0"value="test"/>
  10. </bean>
  11. <beanid="idrefBean1"class="cn.javass.spring.chapter3.bean.IdRefTestBean"
  12. p:id="value"/>
  13. <beanid="idrefBean2" p:id-ref="bean1"/>
  14. </beans>
  • xmlns:p="http://www.springframework.org/schema/p":首先指定p命名空间;
  • <bean id="……" class="……" p:id="value"/>:常量setter注入方式,其等价于<property name="id" value="value"/>;
    • <bean id="……" class="……" p:id-ref="bean1"/>:引用setter注入方式,其等价于<property name="id" ref="bean1"/>。



本来就是比着一本书摘录的,写就是为了自己以后复习使用,这一章写的太长了,而且又乱到时候读的时候一定有麻烦。以后得注意前后呼应的格式了。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


迭代器模式(Iterator)迭代器模式(Iterator)[Cursor]意图:提供一种方法顺序访问一个聚合对象中的每个元素,而又不想暴露该对象的内部表示。应用:STL标准库迭代器实现、Java集合类型迭代器等模式结构:心得:迭代器模式的目的是在不获知集合对象内部细节的同时能对集合元素进行遍历操作
高性能IO模型浅析服务器端编程经常需要构造高性能的IO模型,常见的IO模型有四种:(1)同步阻塞IO(BlockingIO):即传统的IO模型。(2)同步非阻塞IO(Non-blockingIO):默认创建的socket都是阻塞的,非阻塞IO要求socket被设置为NONBLOCK。注意这里所说的N
策略模式(Strategy)策略模式(Strategy)[Policy]意图:定义一系列算法,把他们封装起来,并且使他们可以相互替换,使算法可以独立于使用它的客户而变化。应用:排序的比较方法、封装针对类的不同的算法、消除条件判断、寄存器分配算法等。模式结构:心得:对对象(Context)的处理操作可
访问者模式(Visitor)访问者模式(Visitor)意图:表示一个作用于某对象结构中的各元素的操作,它使你在不改变各元素的类的前提下定义作用于这些元素的新操作。应用:作用于编译器语法树的语义分析算法。模式结构:心得:访问者模式是要解决对对象添加新的操作和功能时候,如何尽可能不修改对象的类的一种方
命令模式(Command)命令模式(Command)[Action/Transaction]意图:将一个请求封装为一个对象,从而可用不同的请求对客户参数化。对请求排队或记录请求日志,以及支持可撤消的操作。应用:用户操作日志、撤销恢复操作。模式结构:心得:命令对象的抽象接口(Command)提供的两个
生成器模式(Builder)生成器模式(Builder)意图:将一个对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示。 应用:编译器词法分析器指导生成抽象语法树、构造迷宫等。模式结构:心得:和工厂模式不同的是,Builder模式需要详细的指导产品的生产。指导者(Director)使用C
设计模式学习心得《设计模式:可复用面向对象软件的基础》一书以更贴近读者思维的角度描述了GOF的23个设计模式。按照书中介绍的每个设计模式的内容,结合网上搜集的资料,我将对设计模式的学习心得总结出来。网络上关于设计模式的资料和文章汗牛充栋,有些文章对设计模式介绍生动形象。但是我相信“一千个读者,一千个
工厂方法模式(Factory Method)工厂方法模式(Factory Method)[Virtual Constructor]意图:定义一个用于创建对象的接口,让子类决定实例化哪一个类,使一个类的实力化延迟到子类。应用:多文档应用管理不同类型的文档。模式结构:心得:面对同一继承体系(Produc
单例模式(Singleton)单例模式(Singleton)意图:保证一个类只有一个实例,并提供一个访问它的全局访问点。应用:Session或者控件的唯一示例等。模式结构:心得:单例模式应该是设计模式中最简单的结构了,它的目的很简单,就是保证自身的实例只有一份。实现这种目的的方式有很多,在Java中
装饰者模式(Decorator)装饰者模式(Decorator)[Wrapper]意图:动态的给一个对象添加一些额外的职责,就增加功能来说,比生成子类更为灵活。应用:给GUI组件添加功能等。模式结构:心得:装饰器(Decorator)和被装饰的对象(ConcreteComponent)拥有统一的接口
抽象工厂模式(Abstract Factory)抽象工厂模式(Abstract Factory)[Kit]意图:提供一个创建一系列相关或相互依赖对象的接口,而无须指定他们具体的类。应用:用户界面工具包。模式结构:心得:工厂方法把生产产品的方式封装起来了,但是一个工厂只能生产一类对象,当一个工厂需要生
桥接模式(Bridge)桥接模式(Bridge)[Handle/Body]意图:将抽象部分与它的实现部分分离,使他们都可以独立的变化。应用:不同系统平台的Windows界面。模式结构:心得:用户所见类体系结构(Window派生)提供了一系列用户的高层操作的接口,但是这些接口的实现是基于具体的底层实现
适配器模式(Adapter)适配器模式(Adapter)[Wrapper]意图:将类的一个接口转换成用户希望的另一个接口,使得原本由于接口不兼容而不能一起工作的类可以一起工作。应用:将图形类接口适配到用户界面组件类中。模式结构:心得:适配器模式一般应用在具有相似接口可复用的条件下。目标接口(Targ
组合模式(Composition)组合模式(Composition)意图:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。应用:组合图形、文件目录、GUI容器等。模式结构:心得: 用户(Client)通过抽象类(Component)提供的公用接口统一
原型模式(Prototype)原型模式(Prototype)意图:用原型实例制定创建对象的种类,并且通过拷贝这些原型创建新的对象。应用:Java/C#中的Clonable和IClonable接口等。模式结构:心得:原型模式本质上就是对象的拷贝,使用对象拷贝代替对象创建的原因有很多。比如对象的初始化构
什么是设计模式一套被反复使用、多数人知晓的、经过分类编目的、代码 设计经验 的总结;使用设计模式是为了 可重用 代码、让代码 更容易 被他人理解、保证代码 可靠性;设计模式使代码编制  真正工程化;设计模式使软件工程的 基石脉络, 如同大厦的结构一样;并不直接用来完成代码的编写,而是 描述 在各种不同情况下,要怎么解决问题的一种方案;能使不稳定依赖于相对稳定、具体依赖于相对抽象,避免引
单一职责原则定义(Single Responsibility Principle,SRP)一个对象应该只包含 单一的职责,并且该职责被完整地封装在一个类中。Every  Object should have  a single responsibility, and that responsibility should be entirely encapsulated by t
动态代理和CGLib代理分不清吗,看看这篇文章,写的非常好,强烈推荐。原文截图*************************************************************************************************************************原文文本************
适配器模式将一个类的接口转换成客户期望的另一个接口,使得原本接口不兼容的类可以相互合作。
策略模式定义了一系列算法族,并封装在类中,它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户。