3.关于程序的耦合
/**
* 程序的耦合
* 耦合:程序间的依赖关系
* 包括:
* 类之间的依赖
* 方法间的依赖
* 解耦:
* 降低程序间的依赖关系
* 实际开发中:
* 应该做到:编译期不依赖,运行时才依赖。
* 解耦的思路:
* 第一步:使用反射来创建对象,而避免使用new关键字。
* 第二步:通过读取配置文件来获取要创建的对象全限定类名
*/
4.工厂模式解耦
在实际开发中我们可以把三层的对象都使用配置文件配置起来,当启动服务器应用加载的时候,让一个类中的方法通过读取配置文件,
把这些对象创建出来并存起来。在接下来的使用的时候,直接拿过来用就好了。那么,这个读取配置文件,创建和获取三层对象的类就是工厂。
5.控制反转
它的核心思想就是:
1、通过读取配置文件反射创建对象。
2、把创建出来的对象都存起来,当我们下次使用时可以直接从存储的位置获取。
这里面要解释两个问题:
第一个:存哪去?
分析:由于我们是很多对象,肯定要找个集合来存。这时候有Map和List供选择。
到底选Map还是List就看我们有没有查找需求。有查找需求,选Map。
所以我们的答案就是
在应用加载时,创建一个Map,用于存放三层对象。
我们把这个map称之为容器。
第二个:什么是工厂?
工厂就是负责给我们从容器中获取指定对象的类。这时候我们获取对象的方式发生了改变。
原来:
现在:
这种被动接收的方式获取对象的思想就是控制反转,它是spring框架的核心之一。
6.
作用:
用于配置对象让spring来创建的。
默认情况下它调用的是类中的无参构造函数。如果没有无参构造函数则不能创建成功。
属性:
id:给对象在容器中提供一个唯一标识。用于获取对象。
class:指定类的全限定类名。用于反射创建对象。默认情况下调用无参构造函数。
scope:指定对象的作用范围。
* singleton :默认值,单例的.
* prototype :多例的.
* request :WEB项目中,Spring创建一个Bean的对象,将对象存入到request域中.
* session :WEB项目中,Spring创建一个Bean的对象,将对象存入到session域中.
* global session :WEB项目中,应用在Portlet环境.如果没有Portlet环境那么globalSession相当于session.
init-method:指定类中的初始化方法名称。
destroy-method:指定类中销毁方法名称。
7.
<bean id="accountService" class="com.itheima.service.impl.AccountServiceImpl"/>
第二种方式:spring管理静态工厂-使用静态工厂的方法创建对象
/**
* 模拟一个静态工厂,创建业务层实现类
*/
public class StaticFactory {
public static AccountService createAccountService(){
return new AccountServiceImpl();
}
}
<bean id="accountService" id属性:指定bean的id用于从容器中获取
class="com.itheima.factory.StaticFactory"
factory-method="createAccountService"></bean>
/**
* 模拟一个实例工厂,创建业务层实现类
* 此工厂创建对象,必须现有工厂实例对象,再调用方法
*/
public class InstanceFactory {
public AccountService createAccountService(){
return new AccountServiceImpl();
}
}
<bean id="instancFactory" class="com.itheima.factory.InstanceFactory"></bean>
<bean id="accountService"
factory-bean="instancFactory"
factory-method="createAccountService"></bean>
依赖注入的三种方式:
1.
使用构造函数的方式,给service中的属性传值
要求:
类中需要提供一个对应参数列表的构造函数。
涉及的标签:
constructor-arg
属性:
index:指定参数在构造函数参数列表的索引位置
type:指定参数在构造函数中的数据类型
name:指定参数在构造函数中的名称 ,用这个找给谁赋值
=======上面三个都是找给谁赋值,下面两个指的是赋什么值的==============
value:它能赋的值是基本数据类型和String类型
ref:它能赋的值是其他bean类型,也就是说,必须得是在配置文件中配置过的bean
作用:
自动按照类型注入。当使用注解注入属性时,set方法可以省略。它只能注入其他bean类型。by type
当有多个类型匹配时,使用要注入的对象变量名称作为bean的id,在spring容器查找,找到了也可以注入成功。找不到就报错。(常用)
作用:
在自动按照类型注入的基础之上,再按照Bean的id注入。它在给字段注入时不能独立使用,必须和@Autowire一起使用;但是给方法参数注入时,可以独立使用。
属性:
value:指定bean的id。
作用:
直接按照Bean的id注入。它也只能注入其他bean类型。 by name
属性:
name:指定bean的id。
作用:
注入基本数据类型和String类型数据的
属性:
value:用于指定值
其他还有一些常用的注解:
用于创建对象的; 相当于:<bean id="" class="">
@Component
作用:
把资源让spring来管理。相当于在xml中配置一个bean。
属性:
value:指定bean的id。如果不指定value属性,默认bean的id是当前类的类名。首字母小写。
@Controller:一般用于表现层的注解。 创建对象的四个注解的作用都是一样的,只是作用层不一样
@Service:一般用于业务层的注解。
@Repository:一般用于持久层的注解。
细节:如果注解中有且只有一个属性要赋值时,且名称是value,value在赋值是可以不写。
作用:
指定bean的作用范围。
属性:
value:指定范围的值。
取值:singleton prototype request session globalsession
@Configuration
作用:
用于指定当前类是一个spring配置类,当创建容器时会从该类上加载注解。获取容器时需要使用AnnotationConfigApplicationContext(有@Configuration注解的类.class)。
属性:
value:用于指定配置类的字节码
@ComponentScan
作用:
用于指定spring在初始化容器时要扫描的包。作用和在spring的xml配置文件中的:
<context:component-scan base-package="com.itheima"/>是一样的。
属性:
basePackages:用于指定要扫描的包。和该注解中的value属性作用一样。
@Bean
作用:
该注解只能写在方法上,表明使用此方法创建一个对象,并且放入spring容器。
属性:
name:给当前@Bean注解方法创建的对象指定一个名称(即bean的id)。
@PropertySource
作用:
用于加载.properties文件中的配置。例如我们配置数据源时,可以把连接数据库的信息写到properties配置文件中,就可以使用此注解指定properties配置文件的位置。
属性:
value[]:用于指定properties文件位置。如果是在类路径下,需要写上classpath:
@Import
作用:
用于导入其他配置类,在引入其他配置类时,可以不用再写@Configuration注解。当然,写上也没问题。
属性:
value[]:用于指定其他配置类的字节码。