Spring — IOC
-
传统方式:先前 service 层调用 dao 实现类:常用 new 方式,高耦合 ( 即依赖 —— 模块与模块之间的联系 )
- 而好的程序应该是:高内聚 ( 模块内部功能的联系 ) 低耦合
-
New 的方式就是写死了,是硬编码 ( 一般来说应该是要避免的 ) 要改变的话就是改源代码
-
将紧耦合变为松耦合,松耦合尽量做到不耦合
-
采用反射方式解耦
-
例:旧方法是需要在参数列表内传入一个 new 的对象,而采用反射思想的话就是直接传入一个字符串,而且字符串可以通过控制台输入
// F1: Scanner sc = new Scanner(System.in); String str = sc.nextLine(); //读取,之后用 str.equals() 根据控制台情况来具体 new 等操作 // F2: Class cls = Class.forName(str); // 填入字符串(类的全包名),用一个Class 类型来接收 cls.newInstance(); // 完成创建:一个控制台输入包的 java 类对象
-
输入字符串,创建了对象 ——> 反射
-
-
反射是框架设计的灵魂,是在程序运行过程中:
-
对任意一个类,都能够 [ 知道 ] 它的所有属性和方法
-
对任意一个对象,都能够 [ 调用 ] 它的所有属性和方法
-
这种动态获取信息以及动态创建对象的功能称为 Java 的反射机制
-
-
Spring 实现解耦的两项技术:
-
反射
-
读配置文件
-
-
Class 对象 ( 类模板,类的模板对象 ) 的获取方式:
-
对象.getClass() 方法
-
类.class属性
-
Class.forName(String className) —— 推荐方法
-
注意:三个方式都是获取的同一个对象,只会执行一次构造方法,即一个类在虚拟机中只能有一个模板对象
-
例:
cls.newInstance("A包名"); A a2 = (A)cls.newInstance(); // 找到模板后,就可以创建对象了
-
class 文件:字节码文件。加载到内存就会生成一个类模板对象,就可以在代码 new 的时候复制粘贴来用了
-
-
反射缺点:效率要低,没直接创建来的快
-
了解:spring 官网下载 spring 是一个压缩包,内 libs 里有 class 的 jar 包、解释 API 文档 javadoc、源码源文件 sources ( 三为一体 ),用得着的话就只拷贝 jar 包就好 —— 早期方法,现都用 maven 方法更便利
第一个 Spring 编码
-
四个基础包 spring-core、beans、context、expression ( 版本要一致 ) 还有 commons-logging 日志基础包,依赖导入时会自动导入 ( Spring 框架依赖于此组件 Apache Commons Logging ),只导 context 也可 ( 其他四个都会自行导入 )
-
xml:
<bean id = "不能重" class = "全包名...X" ></bean> //还可能有 scope 属性表示作用范围,singleton 单例(默认),prototype 是多例,每次使用都会创建对象
-
Test.java:
// psvm ApplicationContext ctx = new ClassPathXmlApplicationContext("1.xml"); // 创建一个大的容器类,ApplicationContext 是个接口,后为实现类,就会到配置文件中把 bean 创建出来 X x = ctx.getBean("bean的id", 类模板—X.class) // 其实就很像A a2 = (A)cls.newInstance(); // x.方法调用(X可以是一个类 / 实现类)
Bean对象的生命周期:
- bean标签的 init-method 属性设置初始化方法
- bean标签的 destroy-method 属性设置销毁方法
- 单例对象的生命周期:容器加载 / 创建时对象便出生,直到容器销毁才死亡,即容器存在对象就一直活着
- 多利对象的生命周期:什么时候用,就什么时候创建 ( 每次使用都会创建 ),对象在使用过程中就会一直活着,死亡交给java垃圾回收机制处理 ( 太多 spring 搞不定 )
IOC 底层原理
-
ioc:控制反转,把对象的创建调用交由 spring 管理,使用目的 —— 降低耦合度
-
ioc 过程:xml 中配 bean <......>,使用工厂类 ( 其实就是容器 ) ApplicationContext = ......,做反射... = ...getBean(...)
-
Spring 提供 IOC 容器实现的两种方式:
-
BeanFactory
BeanFactory xx = new XmlBeanFactory(new ClassPathResource("1.xml")) // 工厂模式 xx.getBean // 用的少,原始方式
-
ApplicationContext —— 是子类,功能更强大,用的更多
其接口有两个实现类
- ClassPathXmlApplicationContext("Name") 用的多:Name 路径:就是 java 或 resource 下的文件名,如:1.xml
- FileSystemXmlApplicationContext("文件路径"):文件路径: D:\idea\Workspace.....
-
Spring IOC 配置 Bean 的两种方式
-
依赖注入 DI ( Dependency Injection ) 是 ioc 的具体体现
-
Bean 的依赖注入值类型:
- 字面值
- 其他 Bean
- 集合类
-
基于 xml 文件的方式 —— 集中式的元数据,与源代码无绑定 ( Bean 的 id 不指定的话就默认为类名 )
- 新建xml的话除了bean等,开头部分还需要加xmlns工作空间,xsi里的 http://...... 约束两个,一共改三处
-
Bean 的依赖关系通常有两种实现方式:
-
构造器注入
- bean 子标签 constructor-arg 里,属性 name、value:只能是基本数据类型 + String ( 除开 String 的引用数据类型不能写入 ) —— 似表单
- 其中 name:注入参数在构造函数中的名称。ref:其他 bean 的 id。value:注入的数据值。在 bean 标签里填写完值后,就可以在 Test 测试时 getBean 后直接输出一串对象值:内容就是 bean 里 value 所写
-
属性 setter 注入
-
属性注入 ( 推荐 ) 用的最多 —— 即把要用的对象当作属性来看,什么时候要什么时候就给你用
属性注入:service 的 bean 子标签 property:name 为所取的属性名 ( != 变量 ),ref 为引用的 daoimpl 的 id
-
-
注意:
- 因为常如以下所用,所用就慢慢默认变量为属性了,实则不是
- name 前提是在 service 所需类里加上 daoimpl 的 getter and setter 方法 ( 方法是针对属性的,而属性就是 bean 里的子标签的 name ),service 里非 new 写的 UserDaoImpl dao 只是一变量,而 xml 里的 name 属性指的是 getXxx 和 setXxx 后面的首字母小写的 xxx ( 但在此处大写也可以 )
- 若是 bean 的 dao 想更换,那就可以直接在 dao 层增加,虽是更改了源码,但实际上新增 dao 可以由别人写,自己只接受其 class 字节码文件即可 ( 跨平台特点 ),不需要编译,可以直接用 ———— bean更方便,解耦
-
-
基于注解的方式 —— 分散式的元数据,与源代码紧绑定
-
在四个 jar 包基础上再加上 aop 依赖包
-
不配置 bean 还想创建出来,就得加一个扫描到包的 context 标签:
<context:component-scan base-package="com.qut" ></context:component-scan>
-
在 serviceimpl 开头加上 ( 即作用到类上 ) @Component(value = “xxxx”) ———— 作用就相当于在 spring 的配置 xml 中写一个 bean 标签
- 没写 value 的话就是类名的首字母小写
-
@Controller ( 用控制器上 - 表现层 )、@Service ( 推荐到 Service 层 - 业务层 )、@Repository ( 推荐 Dao 层 - 持久层 ) —— 作用属性都相同,是 spring 为了提供更明确的语义
-
注意:
-
@Autowired:主要用在只有唯一一个类型匹配,此时 public UserDao ud; 就可以删去 xml 方式时的 get 和 set ud 的方法了
-
@Qualifier 与 @Autowired 搭配使用:当一个 UserDao 有两个 Impl 实现类时,需要在 @Autowired 后再加上 @Qualifier(“xxxImpl”) 指定 service 层用哪个 Impl 实现类
-
@Resource 使用偏少
-
@Value 使用偏少
-
-
代码
// 通过控制台输入信息
Scanner sc = new Scanner(System.in);
// 获取控制台输入字符
String str = sc.nextLine();
// Class可以看作一个模板,找到了str字符串对应模板
Class cls1 = Class.forName(str); // ("com.qut.test.A") -F1
// Class cls1 = a.getClass(); // A a = new A(); -F2
// Class cls2 = A.class; // A a = new A(); -F3
// 完成创建
cls1.newInstance();
// 配成一个大的容器ctx:含有1.xml内的信息
ApplicationContext ctx = new ClassPathXmlApplicationContext("1.xml");
// 通过容器获取A实例 ——— 反射
A a1 = ctx.getBean("mybean1",A.class); // 1.xml里一bean的id为:mybean1
标签:xml,对象,Spring,bean,new,IOC,Class,属性
From: https://www.cnblogs.com/zhu-ya-zhu/p/17488780.html