耦合的概念:

传统的开发中,通常会在main方法或者业务中根据需要创建对应的对象。
public static void main(String []args){
    Obj o = new Obj();
    ....
}

​ 这样的结果就是程序中(不同类之间)的耦合非常大,而带来的问题就是不利于程序后期的维护(试想,当我们因为业务改变而需要修改Obj类或者改为创建新的类时,我们不得不修改源程序,而这违背了面向对象程序设计的开闭原则)。

现在思考如何解决这个问题呢?

  1. 通过反射来加载类(class.forName,我们在加载数据库驱动时经常会这样做)
  2. 通过加载配置文件读取全限定类名[使用propities.getClassLoader.getResourceAsStream相关命令]

tip:有些同学会疑问,这样依然需要写类名,仍然会有耦合。注意,降低耦合并不等于完全消除耦合。

而Spring就是一个完成这样功能框架。[ Spring是一个轻量级控制反转(IoC)和面向切面(AOP)的容器框架 —–摘自百度百科]

关于控制反转:控制反转的主要作用是降低耦合,为什么叫做控制反转呢?我们将在下文中提到。

关于 bean:编程英语中bean通常指的是可重用组件,而在Java中一般指类。

Spring如何使用呢?

  1. 创建bean.xml [可参考官网, 最小仅需要id和class属性。]

一个简单的bean.xml的例子:

<bean id="accountService" class="top.4fan.dy.service.impl.AccountServiceImpl"></bean>
  1. 创建对应的所需要获得的对象对应的类文件。
  2. 在需要的位置(比如main)通过如下方式获得需要的对象:
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml")
    //一下两种方法无本质区别
Obj o1 = (Obj)ac.getBean("xml里边的id");
Obj o2 = ac.getBean("xml里边的id",xxx.class);//这种方法不需要强转

ApplicationContext类有三个常用的实现类(我们以上仅用到一种,其它的用法场景如下):

  • ClassPathXmlApplicationContext :加载类路径下的配置文件【配置文件必须在类路径下】

  • FileSystemXmlApplicationContext:加载磁盘上任意有权限[指操作系统级别的权限]的文件

  • AnnotationConfigApplicationContext:读取注解创建容器

​ 所有的ApplicationContext类都有立即加载的特征,即``new xxxApplicationContext时即创建对象。与之相对应的另一种用于获得对象的XmlBeanFactory`(3.1已被标注放弃)类则在需要时创建对象。对于未使用到的另外两个常用类,可以参考Spring文档。

所以最后一个问题,为什么叫做控制反转呢?

​ 在传统的代码中,我们通过自己创建对象并控制对象的生命周期(初始化……销毁),而使用Spring时,对象的生命周期则由Spring管理,即我们把对象的控制权交给了Spring容器。

tip:如果你对面向对象程序设计中的设计模式部分比较熟悉的话,你可以将Spring理解为一个工厂模式的实现。

// 补充AnnotationConfigApplicationContext   demo
// 在配置类上添加注解的方式来替代xml配置文件
// 1. 配置类上添加 @ComponentScan([扫描路径])并且在bean类上添加@Component注解
// 2. 在配置类的方法上添加@Bean注解

ApplicationContext ac = new AnnotationConfigApplicationContext(Config.Class)
ac.getBean("user");

//法1  可参考下方关于相关注解的说明
@ComponentScan("com.example")
public class Config(){
    
}
@Component
public class User{}
// 法2  
public class Config(){
    @Bean
    public User user(){
        return new User();
    }
}

Spring补充笔记

concepts

IOC[Inversion of Control]控制反转的作用:降低耦合。

bean:可重用组件(java中一般指类)

AOP 面向切面编程[通过动态代理]—->解耦合

依赖注入:Dependency Injection即依赖关系的维护,

spring对Bean的管理细节

创建bean的三种方式
  1. 在xml中bean标签仅配置id和class采用默认构造参数(无参)创建bean对象。[使用account的默认构造]
<bean id="accountService" class="top.4fan.dy.service.impl.AccountServiceImpl"></bean>
  1. 使用普通工厂中的方法创建对象(使用某个类中的方法创建对象并存入spring容器)[jar包中的类]
<bean id="instanceFactory" class="top.4fan.dy.factory.InstanceFactory"></bean>
<bean id="accountService" factory-bean="instanceFactory" factory-method="getAccountService"></bean>[第二行的bean的factory-bean指向上一行]
  1. 使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象并存入spring容器)
bean id="accountService" class="top.4fan.dy.StaticFactory" factory-method="getAccountService"></bean>[用class中的静态方法创建]
bean的作用范围
使用bean的 scope属性调整:
  • singleton:单例,默认值
  • prototype:多例
  • request: 作用于web应用的请求范围
  • session:作用于web应用的会话范围
  • global-session:作用于集群环境的会话范围,当不是集群环境就是session
bean的声明周期
  • 单例:
    • 创建: 容器创建时 (也可以懒加载:lazy-init=true)
    • 死亡: 容器销毁时
  • 多例:
    • 创建:使用对象时创建
    • 死亡: 由GC完成

依赖注入:Dependency Injection即依赖关系的维护

注入目标
  • 基本类型
  • String
  • 其它Bean类型(配置文件中或注解配置过的bean),复杂类型(集合类型)
注入方式
  • 构造函数注入: constructor-arg标签的属性:type,index,name用于指定给哪个参数赋值,value,ref为值 [ref的值为另一个bean标签的id[即其它对象,比如日期]]

  • set方法注入: 属性:name,value,ref 优点:创建对象时没有明确的限制,可以直接使用默认的构造函数 缺点:若某个成员必须有值,set方法无法保证一定注入。[优缺点和构造函数注入相反,更常用]

  • 使用注解

常用注解

用于创建对象的:xml中的bean的功能
  • @Component:将当前类对象存入spring容器中,可通过value指定bean的id,默认为当前类名且首字母小写
  • @Controller【表现层】,@Service【业务层】,@Respository【持久层+改名】 这三个注解的作用与Component完全一样,是spring提供的三层明确的注解使得三层对象更加清晰。
用于注入数据的:xml中的bean中的property
  • @Autowired:自动按照类型注入,只要容器中有唯一的一个bean对象和要注入的类型匹配就可以注入成功。可以出现在变量上或者方法上。如果容器中满足类型匹配的对象有多个时取要注入的变量名字与class名相同的,否则报错。
  • @Qualifier(value=类名),用于指定类名,但必须与Autowired结合使用
  • @Resource(name=“类名”),<===>@Autowired + @Qualifier 以上三个注解只能注入其它bean类型的数据,基本类型数据和String类型无法使用上述注解。另外集合类型只能通过XML实现。
  • @Value:用于注入基本类型和String类型。属性:value用于指定数据的值。可以使用spring的Spel表达式 ${}
用于改变作用范围的:scope
  • @Scope() eg:@Scope(“prototype”)多例【spring不负责多例对象的销毁,由GC负责】
和声明周期相关的:init-method/destory-method
  • @PostConstruct/@PreDestroy【了解即可】

  • @Configuration 指明当前类是一个配置类<相当于一个Spring配置的xml文件>–>替代以下的SpringConfiguration.class–>写一个主要的为参数,主要的类加ComponentScan,其他的加Configuration。也可以在主要的下边用Import注解导入其它参数类。

  • @ComponentScan 用于通过注解指定Spring创建容器时要扫描的包。扫描包下所有使用@Service,@Component…..等四个注解的类并注册为bean。 属性:basePackage和value具有相同作用,用于创建容器时要扫描的包。等同于xml中的 <context:component-scan base-package:“com.abc."> 然后将ApplicationContext ac = new ClassPathXmlApplicationContext(“bean.xml”)改为 ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);

  • @Bean 将当前方法返回的对象放入Spring IOC容器中 属性:name用于指定bean的id,默认值:当前方法的名称。 如果方法有参数则去spring容器中找,查找方式和Autowired注解一样

  • @Import 指定其它配置类的字节码

  • @PropertySource(“classpath:[包名]application.properties”)

接口命名规范demo:IAccountService