预备知识

1、什么是spring
1什么是Spring
Spring是一个开源框架,Spring是于2003年兴起的一个轻量级的Java开发框架,由Rod Johnson在其著作Expert One-On-One J2EE Development and Design中阐述的部分理念和原型衍生而来。它是为了解决企业应用开发的复杂性而创建的。框架的主要优势之一就是其分层架构,分层架构允许使用者选择使用哪一个组件,同时为J2EE应用程序开发提供集成的框架。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。Spring的核心是控制反转( IoC )和面向切面( AOP ).简单来说,Spring是一个分层的JavaSE/EEfull-stack(一站式)轻量级开源框架
Spring主要的目的:简化企业开发
2、Spring核心
Spring的核心是控制反转( loC)和面向切面(AOP )。
1.2 Spring框架的优点
- 方便解耦,简化开发
通过 Spring提供的loC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 - AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,许多不容易用传统OOP实现的功能可以通过AOP轻松应付。 - 声明式事务的支持
在Spring 中,我们可以从单调烦闷的事务管理代码中解脱出来,通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 - 方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring 对Junit4支持,可以通过注解方便的测试Spring程序。 - 方便集成各种优秀框架
Spring 不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz )等的直接支持。 - 降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBc,JavaMail,远程调用等)提供了一个薄薄的封装层,通过Spring 的简易封装,这些Java EE API的使用难度大为降低。 - . Java源码是经典学习范例
Spring 的源码设计精妙、结构清晰、匠心独用,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring 框架源码无疑是Java技术的最佳 - 实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。
3、初识spring

Spring一共有十几个组件,但是真正的核心组件只有几个,我们一起来看下Spring框架的总体架构图,了解一下他的体系结构。
从这个图中我们可以看出Spring框架的核心组件只有三个:Core、Context和Beans。他们构建起了整个Spring的骨骼架构,没有他们就不可能有AOP、Web等上层的特性功能。上面这些是Spring特性功能。
我列举了比较重要的几个包:AOP包(主要提供面向切面编程的实现),Web(主要提供了Web应用开发的支持及针对Web应用的MVC思想实现)、ORM(为我们之前学的Hibernate,以及以后会学到的Mybatis这类持久化框架提供支持)、还有Spring MVC (这个是它自带的一个web视图层,可以替代到Sturts2,将来我们还会详细的学习这个SpringMVC框架)。。等等,其中最最核心的就是AOP和下面Spring核心包,也是我们学习的重点
1.4 Spring的两大核心技术
控制反转(IoC : lnversion of Control ) /依赖注入(DI : Dependency Injection )面向切面编程(AOP : Aspect Oriented Programming)
二、Spring入门程序
1、在pom.xml添加spring的相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.2.7.RELEASE</version>
</dependency>
2、在main/resources创建beans.xml文件(spring配置文件)
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
3、编写组件完成操作
package com.woniuxy;
public class HelloWorld {
public String sayHello(String name){
return "Hello"+name+"!";
}
}
4、在Spring的配置文件中声明定义这个bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- 如下结点相当于调用无参构造方法完成对象的实例化,HelloWorld helloworld=new HelloWorld()
id:bean对象的唯一标识
class:类全名
-->
<bean id="hello" class="com.woniuxy.HelloWorld"></bean>
</beans>
5、测试
private Logger logger = Logger.getLogger(this.getClass());
@Test
public void testHelloworld()
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Object obj=context.getBean("hello");
if (obj instanceof HelloWorld){
HelloWorld hw=(HelloWorld) obj;
logger.info(hw.sayHello("Spring "));
}
}
三、Spring的核心容器
Spring提供了两种核心容器,分别是BeanFactory和ApplicationContext
1 、BeanFactory
BeanFactory是基础类型的STOC容器,它提供了完整的TOC服务支持,简单来说,BeanFacory就是一个管理Bean的工厂,它主要负责初始化各种Bean,并调用它们的生命周期方法
BeanFactory接口有多个实现类,最常见的是XmlBeanFactory
@Test
public void testBeanFactory(){
BeanFactory factory = new XmlBeanFactory(new FileSystemResource("E:\\IDEA\\WN-Spring\\spring-01-quickstart\\src\\main\\resources\\beans.xml"));
Object obj=factory.getBean("hello");
if(obj instanceof HelloWorld){
HelloWorld hw=(HelloWorld) obj;
logger.info(hw.sayHello("Giles"));
}
}
2、ApplicationContext
AppicationContext是BeanFactory的子接口,ApplicationContext不仅包含了BeanFactory的所有功能,还添加了对国际化,资源访问,事件传播等方面的支持ApplicationContext接口有两个常用的实现类,具体如下所示
. ClassPathXmlApplicationContext:该类从类路径中寻找指定的XML配置文件
. FileSystemXmlApplicationContext:该类从指定的文件系统中寻找指定的XML配置文件
在WEB项目中,, ApplicationContext容器的实例化工作会交由WEB服务器完成,WEB服务器实例化ApplicationContext容器通常使用基于ContextLoaderlistener实现的方式,它需要在web.xml中添加如下代码
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:applicationContext.xml</param-value></context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
3 BeanFactory和ApplicationContext的主要区别:
如果Bean的某一个属性没有注入,则使BeanFactory加载后,在第一次调用getBean()方法时会抛出异常
而ApplicationContext则在初始化时自检,这样有利于检
查所依赖的属性是否注入。
因此,在实际开发过程中,通常都选择使用ApplicationContext,而只有在系统资源较少时,才考虑使用BeanFactory。
四、Spring IOC和DI概念理解(重中之重)
1、IOC(控制反转)降低程序的耦合性
(1)IOC(控制翻转)控制反转(IOC )
依赖注入( Dependency Injection,简称DI )
IOC和DI是一回事,只是在不同的角度去诠释同一个问题1)控制反转(IOC )
使用Spring之前

使用Spring之后

由代码来维护程序之间的关系,有了spring容器之后,程序之间的这种关系,控制权由应用程序转移到到了Spring容器,控制器权发生了反转,这就是spring的控制反转,称为IOC
DI(依赖注入)
从另外一个角度来说明

所谓的依赖注入:在程序运行的过程中临时组装各组件(各组件之间要有合适的接口)
思考:是不是所有的组件都需要放在Spring容器中来管理?不是的
五、依赖注入的实现方式
有两种放心可以进行注入,setter方式(使用更多),构造方法注入
1、SET方式的注入
1)、基本数据类型的注入
简单数据类型
|–基本数据类型: byte、short、int、long、float、double、Boolean、char
|–引用数据类型String
使用value属性或者value来实现注入的
pojo实体类:
public class Student {
private String name;
private int age;
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "name:"+name+"年龄"+age;
}
}
beans.xml配置
<!-- 简单类型的注入-->
<bean id="student1" class="com.woniuxy.pojo.Student">
<property name="name" value="张三"></property>
<property name="age">
<value>18</value>
</property>
</bean>
<!--
如果遇到特殊字符,XML中的解决办法有两种
1、通过转义字符:比如:P&G
2、通过<!CDATA[]>方式来进行转义
-->
<bean id="student2" class="com.woniuxy.pojo.Student">
<property name="name" value="P&G"></property>
<property name="age" value="16"></property>
</bean>
<bean id="student3" class="com.woniuxy.pojo.Student">
<property name="name">
<value><![CDATA[P&G]]></value>
</property>
<property name="age" value="16"></property>
</bean>
测试:
public void testDi1()
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student= (Student) context.getBean("student1");
logger.info(student);
}
2)注入bean对象类型
package com.woniuxy.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class Dept implements Serializable{
private byte deptno;
private String dname;
private String loc;
private List<Emp> emps;
}
package com.woniuxy.pojo;
import lombok.Data;
import java.io.Serializable;
import java.util.Date;
@Data
public class Emp implements Serializable{
private short empno;
private String ename;
private String job;
private short mgr;
private Date hiredate;
private double sal;
private double comm;
private Dept dept;
}
package com.woniuxy.dao;
import com.woniuxy.pojo.Dept;
import java.util.List;
public interface DeptDao {
public List<Dept> findAll();
}
package com.woniuxy.dao.impl;
import com.woniuxy.dao.DeptDao;
import com.woniuxy.pojo.Dept;
import org.apache.log4j.Logger;
import java.util.List;
public class DeptDaoImpl implements DeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List<Dept> findAll() {
logger.info("使用mybatis实现部门的查询操作");
return null;
}
}
package com.woniuxy.dao.impl;
import com.woniuxy.dao.DeptDao;
import com.woniuxy.pojo.Dept;
import org.apache.log4j.Logger;
import java.util.List;
public class DeptDaoJpaImpl implements DeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List<Dept> findAll() {
logger.info("使用spring data JPA实现部门的查询");
return null;
}
}
package com.woniuxy.service;
import com.woniuxy.pojo.Dept;
import java.util.List;
public interface DeptService {
public List<Dept> findAllDepts();
}
package com.woniuxy.service.impl;
import com.woniuxy.dao.DeptDao;
import com.woniuxy.pojo.Dept;
import com.woniuxy.service.DeptService;
import java.util.List;
public class DeptServiceImpl implements DeptService {
private DeptDao deptDao;
public void setDeptDao(DeptDao deptDao) {
this.deptDao = deptDao;
}
@Override
public List<Dept> findAllDepts() {
return deptDao.findAll();
}
}
<!-- bean的注入 -->
<bean id="deptDao" class="com.woniuxy.dao.impl.DeptDaoImpl"></bean>
<bean id="deptJpaDao" class="com.woniuxy.dao.impl.DeptDaoJpaImpl"></bean>
<bean id="deptService" class="com.woniuxy.service.impl.DeptServiceImpl">
<!-- <property name="deptDao" ref="deptJpaDao"></property>-->
<property name="deptDao">
<ref bean="deptJpaDao"></ref>
</property>
</bean>
@Test
public void testDi2()
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
DeptService deptService = (DeptService) context.getBean("deptService");
deptService.findAllDepts();
}
3)注入集合类型
常用的集合 List、set、Map、Properties(主要做配置)
3.1)注入List集合
package com.woniuxy.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class Person {
private List<String> names;
private Set<String> inserts;
private Map<String,String> wifes;
private Properties jobs;
public void setJobs(Properties jobs) {
this.jobs = jobs;
}
public void setWifes(Map<String, String> wifes) {
this.wifes = wifes;
}
public void setInserts(Set<String> inserts) {
this.inserts = inserts;
}
public void setNames(List<String> names) {
this.names = names;
}
@Override
public String toString() {
return "Person{" +
"names=" + names +
", inserts=" + inserts +
", wifes=" + wifes +
", jobs=" + jobs +
'}';
}
}
<!--注入List集合-->
<bean id="person" class="com.woniuxy.pojo.Person">
<property name="names">
<list>
<value>张三</value>
<value>李四</value>
</list>
</property>
<property name="inserts">
<set>
<value>AAAA</value>
<value>BBBB</value>
</set>
</property>
<property name="wifes">
<map>
<entry key="first">
<value>CCCC</value>
</entry>
<entry key="sec">
<value>DDDD</value>
</entry>
</map>
</property>
<property name="jobs">
<props>
<prop key="1">EEEEE</prop>
<prop key="2">FFFFF</prop>
</props>
</property>
</bean>
@Test
public void testDi3()
{
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Person person = (Person) context.getBean("person");
logger.info(person);
}
@Test
public void testProperties(){
Properties pro=new Properties();
InputStream in = this.getClass().getClassLoader().getResourceAsStream("datasource.properties");
try {
pro.load(in);
logger.info(pro.getProperty("driver"));
logger.info(pro.getProperty("url"));
logger.info(pro.getProperty("username"));
logger.info(pro.getProperty("password"));
} catch (IOException e) {
e.printStackTrace();
}
}
@Test
public void testProperties2(){
Properties pro=new Properties();
pro.setProperty("driver","com.mysql.jdbc.Driver");
pro.setProperty("url","jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8");
pro.setProperty("username","root");
pro.setProperty("password","123456");
OutputStream os= null;
try {
os = new FileOutputStream("E:\\IDEA\\WN-Spring\\spring-02-di\\src\\main\\resources\\datasource.properties");
pro.store(os,"datasource.properties");
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
4)构造子注入注入(构造方法注入)
package com.woniuxy.pojo;
public class Teacher {
private String name;
private Integer lessionAge;
private Double score;
private String school;
public Teacher(String name, Integer lessionAge, Double score) {
this.name = name;
this.lessionAge = lessionAge;
this.score = score;
}
public Teacher(String name, Integer lessionAge, Double score, String school) {
this.name = name;
this.lessionAge = lessionAge;
this.score = score;
this.school = school;
}
@Override
public String toString() {
return "Teacher{" +
"name='" + name + '\'' +
", lessionAge=" + lessionAge +
", score=" + score +
", school='" + school + '\'' +
'}';
}
}
<!-- 构造方法注入-->
<bean id="teacher" class="com.woniuxy.pojo.Teacher">
<constructor-arg index="0" value="刘老师"></constructor-arg>
<constructor-arg index="1" value="12"></constructor-arg>
<constructor-arg index="2" value="10"></constructor-arg>
</bean>
<bean id="teacher2" class="com.woniuxy.pojo.Teacher">
<constructor-arg name="name" value="张三"></constructor-arg>
<constructor-arg name="lessionAge" value="11"></constructor-arg>
<constructor-arg name="score" value="12"></constructor-arg>
</bean>
<!-- 使用这种类型,必须在实体对象中使用包装类型,而且有多个同类型,还要注意顺序-->
<bean id="teacher3" class="com.woniuxy.pojo.Teacher">
<constructor-arg type="java.lang.String" value="李四"></constructor-arg>
<constructor-arg type="java.lang.Integer" value="13"></constructor-arg>
<constructor-arg type="java.lang.Double" value="15"></constructor-arg>
<constructor-arg type="java.lang.String" value="嘻嘻嘻嘻嘻嘻"></constructor-arg>
</bean>
@Test
public void testDi5(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Teacher teacher = (Teacher) context.getBean("teacher");
logger.info(teacher);
}
@Test
public void testDi52(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Teacher teacher = (Teacher) context.getBean("teacher2");
logger.info(teacher);
}
@Test
public void testDi53(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Teacher teacher = (Teacher) context.getBean("teacher3");
logger.info(teacher);
}
5) P命令空间注入(了解)
xmlns:p="http://www.springframework.org/schema/p" //在bean的顶部加入
<!-- P命名空间注入-->
<bean id="student4" class="com.woniuxy.pojo.Student" p:name="王小明" p:age="23"></bean>
</beans>
@Test
public void testStudent4(){
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student) context.getBean("student4");
logger.info(student);
}
6)自动装配(了解)
使用xm进行注入的时,大家会发现配置文件的内容越来越多,XMNL的可读性不是很高,而且XML中配置内容过多也是一份工作量,开始想办法去减少配置,自动配置就可以减少配置。
要使用自动装配,就需要配置元素的autowire属性。autowire属性有五个值,具体说明如下。
| 取值 | 说明 |
|---|---|
| (1)no | 默认值。Spring默认不进行自动装配,必须显式指定依赖对象 |
| (2)byName | 根据属性名白动装配。Spring自动查找与属性名相同的id,如果找到,则白动注入,否则什么都不做根据属性的类型白动装配。Spring自动查找与屈性类型相同的Bean, |
| (3)by Type | 如果刚好找到唯一的那个,则白动注入;如果找到多个与屁性类型相同的Bean,则抛出异常;如果没找到,就什么也不做 |
| (4)constructor | 和byType类似,不过它针对构造方法。如果Spring找到一个Bean和构造方法的参数类型相匹配,则通过构造注入该依赖对象;如果找不到,将抛出异常 |
<bean id="deptService" class="com.woniuxy.service.impl.DeptServiceImpl"> <!-- autowire="byName"-->
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-autowire="byName">
7)使用注解完成自动装配(重点掌握)
在之前已经XML配置了,使用大量的XML配置,使得整个项目变得非常的臃肿,Spring主要的目标是简化企业开发,提高开发效率,学习框架以后,没减轻工作量,反而工作量变大,有着大量的XML配置,XML配置的年代过度到注解配置的时代,XML的配置依然存在,主要是以注解为主,XML为辅
在使用注解之前必须要在spring的配置文件中配置扫描注解的位置,否则虽然已经在类的前面添加@Component,但是spring配置文件,并没有找到这个位置.
@Component:所有的组件都可以使用这个注解
@Component就相当于在spring配置文件中完成的声明,就相当于是实例化对象
类型唯一:
package com.woniuxy.dao;
import java.util.List;
public interface IDeptDao {
public List findAll();
}
package com.woniuxy.dao.impl;
import com.woniuxy.dao.IDeptDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import java.util.List;
@Component
/*
* @Component的作用就相当于在Spring 的配置文件中声明了bean
* <bean id="deptDaoImpl" class="com.woniuxy.dao.DeptDaoImpl" /> id值,class类型首字母小写
* 注意:如果这个@Component要被Spring容器所识别,别需要在扫描的包下
* */
public class DeptDaoImpl implements IDeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List findAll() {
logger.info("使用mybatis查询所有的部门信息");
return null;
}
}
package com.woniuxy.service;
import java.util.List;
public interface IDeptService {
public List findAllDept();
}
package com.woniuxy.service.impl;
import com.woniuxy.dao.IDeptDao;
import com.woniuxy.service.IDeptService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class DeptServiceImpl implements IDeptService {
@Resource//依赖注解
/*@Resource 首先按照名称进行自动装配,如果名称对应不上,则按照类型进行自动装配
*
* **/
private IDeptDao iDeptDao;
@Override
public List findAllDept() {
return iDeptDao.findAll();
}
}
测试
@Test
public void test()
{
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
IDeptService deptService =(IDeptService) context.getBean("deptServiceImpl");
deptService.findAllDept();
}
类型不唯一:@Resource
package com.woniuxy.dao.impl;
import com.woniuxy.dao.IDeptDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("deptDaoJpa")
public class DeptDaoJpaImpl implements IDeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List findAll() {
logger.info("使用Spring Data JPA查询所有的部门信息");
return null;
}
}
package com.woniuxy.service.impl;
import com.woniuxy.dao.IDeptDao;
import com.woniuxy.service.IDeptService;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class DeptServiceImpl implements IDeptService {
@Resource(name = "deptDaoJpa")
//依赖注解
/*@Resource 首先按照名称进行自动装配,如果名称对应不上,则按照类型进行自动装配
*
* **/
private IDeptDao iDeptDao;
@Override
public List findAllDept() {
return iDeptDao.findAll();
}
}
类型不唯一:@autowired @Qualifier
package com.woniuxy.dao.impl;
import com.woniuxy.dao.IDeptDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("deptDaoMybatis")
/*
* @Component的作用就相当于在Spring 的配置文件中声明了bean
* <bean id="deptDaoImpl" class="com.woniuxy.dao.DeptDaoImpl" /> id值,class类型首字母小写
* 注意:如果这个@Component要被Spring容器所识别,别需要在扫描的包下
* */
public class DeptDaoImpl implements IDeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List findAll() {
logger.info("使用mybatis查询所有的部门信息");
return null;
}
}
package com.woniuxy.dao.impl;
import com.woniuxy.dao.IDeptDao;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;
import java.util.List;
@Component("deptDaoJpa")
public class DeptDaoJpaImpl implements IDeptDao {
private Logger logger=Logger.getLogger(this.getClass());
@Override
public List findAll() {
logger.info("使用Spring Data JPA查询所有的部门信息");
return null;
}
}
package com.woniuxy.service.impl;
import com.woniuxy.dao.IDeptDao;
import com.woniuxy.service.IDeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.List;
@Component
public class DeptServiceImpl implements IDeptService {
//@Resource(name = "deptDaoJpa")
//依赖注解
/*@Resource 首先按照名称进行自动装配,如果名称对应不上,则按照类型进行自动装配
*
* **/
@Autowired //首先按类型匹配,如果类型一样则可以匹配成功
@Qualifier("deptDaoMybatis")//在qualifier协商需要匹配的类型的名字,与autowired组合使用
//如果自动装配的过程中发现,同一类型的对象有多个,则需要结合@Qualifier来指定要装配的对象的名称,方能唯一的装配
private IDeptDao iDeptDao;
@Override
public List findAllDept() {
return iDeptDao.findAll();
}
}
其他注解
如果上所有的组件都是用的@Component ,但是在实际开发过程中使用@Compent,虽然也能完成Bean实例化声明,但是不能见名知意,Spring提供了如下注解
Repository:用于声明DAO层的
service:用于业务层
Controller:用于控制器
关于扫描包的问题
context:exclude-filter排除扫描哪个注解
context:include-filter :只扫描哪个注解
六、Spring中的bean
1、实例化bean(了解)
Spring bean有三种方式
1、构造方式方法的方式(最常用)
<bean id="student1" class="com.woniuxy.pojo.Student">
<property name="name" value="张三"></property>
<property name="age">
<value>18</value>
</property>
</bean>
2、静态工厂的方式
public class MyFactory {
public static Person createPerson(){
return new Person();
}
<!--
静态工厂方式创建bean对象class:工厂的类全名
factory-method:静态工厂方法-->
<bean id="person" class="com.woniuxy.factory.MyFactory" factory-method="createPerson"></bean>
3、实例工厂方式
package com.woniuxy.factory;
import com.woniuxy.pojo.Person;
public class PersonFactoryInstance {
public Person createPerson(){
return new Person();
}
}
<bean id="personFactoryInstane" class="com.woniuxy.factory.PersonFactoryInstance"></bean>
<bean id="person2" class="com.woniuxy.pojo.Person" factory-bean="personFactoryInstane" factory-method="createPerson"></bean>
@Test
public void testFacory2()
{
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
Person person =(Person)context.getBean("person2");
logger.info(person);
}
2、bean的作用域(理解)
spring中为bean的实例定义了7种作用域,这7种作用域说明如下表所示在bean节点中通过scope属性来设置bean的作用域
| 作用域 | 说明 |
|---|---|
| singleton | 默认值。Spring以单例模式创建Bean的实例,即容器中该Bean的实例只有一个 |
| prototype | 每次从容器中获取Bean时,都会创建一个新的实例 |
| request | 用于Web应用环境,针对每次HTTP请求都会创建一个实例 |
| session | 用于Web应用环境,同一个会话共享同一个实例,不同的会话使用不同的实例 |
| global session | 仅在Portlet的Web应用中使用,同一个全局会话共享一个实例。对于非Portlet环境,等同于session |
7种作用域种singleton和prototype最常用的两种
2.1 singleton作用域
2.2 prototype作用域
3、Bean生命周期[理解]
1、什么bean的生命周期
通过new的方式创建一个对象,从创建到销毁过程称为这个bean的生命周期
spring中bean的生命周期是什么样子呢?
从创建到销毁的过程 两种作用域的生命周期是不一样的
案例
<!--
在spring的bean节点中通过
init-method:初始化方法
destory-method:销毁方法
1)如果scope为singleton,如果单例,实际上初始化spring容器的时候调用
销毁方法是在spring容器销毁的时候会被调用,实际上单例的对象和spring容器的生命周期是一样的
bean:实例化初始化销毁容器:实例化销毁
2)如果是scope为多例,bean的生命周期,实际上每次调用getBean()开始创建对象,容器即便销毁了,对象的销毁方法也不会执行实例化(getBean())初始化通过程序销毁
-->
Spring容器可以管理singleton作用域Bean的生命周期,在此作用域下,Spring能够精确地知道该Bean何时被创建,何时初始化完成,以及何时被销毁。而对于
prototype作用域的Bean , Spring只负责创建,当容器创建了Bean的实例后,Bean的实例就交给客户端代码管理,Spring容器将不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会创建一个新的实例,并且不会管那些被配置成prototype作用域的Bean的生命周期。
了解Spring生命周期的意义就在于,可以利用Bean在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在Bean被初始化后和被销毁前执行一些相关操作。
在Spring中 , Bean的生命周期是一个很复杂的执行过程,我们门可以利用Spring提供的方法定制Bean的创建过程。当一个Bean被加载到Spring容器时,它就具有了生命,而Spring容器在保证一个Bean能够使用之前,会进行很多工作。Spring容器中Bean的生命周期流程
<!--
实例化bean的三种方式
1、通过构造方法来构造
2、通过静态工厂来创建
如下属性的含义
|-class :静态工厂的类全名
|-factory-method:工厂类中的静态方法
3、通过实例工厂创建
-->
<bean id="person1" class="com.woniuxy.factory.PersonFactory" factory-method="createPerson" scope="prototype"></bean>
<bean id="personFactoryInstane" class="com.woniuxy.factory.PersonFactoryInstance"></bean>
<bean id="person2" class="com.woniuxy.pojo.Person" factory-bean="personFactoryInstane" factory-method="createPerson" scope="prototype"></bean>
<!--bean的作用域,通过scope属性来指定,指定的有两个,默认值的是sigleton单例,prototype:多例-->
<bean id="date" class="java.util.Date" scope="prototype"></bean>
<!--bean的生命周期 -->
<bean id="person3" class="com.woniuxy.pojo.Person" init-method="init" destroy-method="destory" scope="singleton">
<property name="name" value="张无忌"></property>
<property name="age" value="21"> </property>
</bean>
单例对象------在spring容器创建的时候实例化
多例对象------在调用getBean的时候采取实例化
单例对象------->当spring容器销毁的时候他也销毁
多例对象------->容器销毁不会调用destroy-method-------多例的销毁由自己来
Spring容器可以管理singleton作用域Bean的生命周期,在此作用域下,Spring能够特确地知道该Bean何时被创建,何时初始化完成,以及何时被销毁。而对于prototype作用域的Bean , spring只负责创建,当容器创建了Bean的实例后,Bean的实例就交给客户端代码管理,Spring容器将不再跟踪其生命周期。每次客户端请求prototype作用域的Bean时,Spring容器都会创建一个新的实例,并且不会管那些被配置成prototype作用域的Bean的生命周期。
了解Spring生命周期的意义就在于,可以利用Bean在其存活期间的指定时刻完成一些相关操作。这种时刻可能有很多,但一般情况下,会在Bean被初始化后和被销毁前执行一些相关操作。
在Spring中, Bean的生命周期是一个很复杂的执行过程,我和们可以利用Spring提供的方法定制Bean的创建过程。当一个Bean被加载到Spring容器时,它就具有了生命,而Spring容器在保证一个Bean能够使用之前,会进行很多工作。Spring容器中Bean的生命周期流程

Bean生命周期的整个执行过程描述如下。
(1)根据配置情况调用Bean构造方法或工厂方法实例化Bean。
(2)利用依赖注入完成Bean中所有属性值的配置注入。
( 3 )如果Bean实现了BeanNameAware接口,则Spring调用Bean的setBeanName()方法传入当前Bean的lid值。
(4)如果Bean实现了BeanFactoryAware接口,则Spring调用setBeanFactory()方法传入当前工厂实例的引用。
(5 )如果Bean实现了ApplicationContextAware接口,则Spring调用setApplicationContext()方法传入当前ApplicationContext实例的引用。
(6)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的预初始化方法postProcessBeforeiIntialzation()对SBean进行加工操作,此处非常重要,Spring的AOP就是利用它实现的
(7)如果Bean实现了InitializingBean接口,则Spring将调用afterPropertiesSet()方法。
(8)如果在配置文件中通过init-method属性指定了初始化方法,则调用该初始化方法。
(9)如果BeanPostProcessor和Bean关联,则Spring将调用该接口的初始化方法postProcessAfternitialization()。此时,Bean已经可以被应用系统使用了。
(10 )如果在中指定了该Bean的作用范围为scope=“singleton”,则将该Bean放入Spring IoC的缓存池中,将触发Spring对该Bean的生命周期管理;如果在中指定了该Bean的作用范围为scope="prototyp e”;则将该Bean交给调用者,调用者管理该Bean的生命周期,Sprinq不再管理该Bean
(11)如果Bean实现了DisposableBean接口,则Spring会调用destory()方法将Spring中的Bean销毁
如果在配置文件中通过destory-method属性指定了Bean的销毁方法,则Spring将调用该方法对Bean进行销毁。
Spring为Bean提供了细致全面的生命周期过程,通过实现特定的接口或的属性设置,都可以对Bean的生命周期过程产生影响。虽然可以随意配置的属性,但是建议不要过多地使用Bean实现接口,因为这样会导致代码和Spring的聚合过于紧密
4、spring配置文件的拆分【掌握】
在企业中随着项目内容不断增加,同时配置信息越来越多,把所有的配置信息放在同一个配置文件,把着这个配置文件就会变得越来越臃肿,可读性也会降低,查询配置信息,具体拆分的策略,由项目具体而定
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.orK/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd""><import resource="beans-first.xml"></import>
<import resource="beans-second.xml"></import>
<import resource="beans-third.xml"></import>
<import resource="beans-fourth.xml"></import>
</beans>
<xml version="1.o" encoding="UTF-8"?>
<beans xmlns="http: // www.springframework.orglschema/beans"
xmlns:xsi="http: / /www.w3.org/2001/XMLSchema-instance"
xsi: schemaLocation="http:// www. springframework. orglschema/beans
http: //www.springframework.org/schema/beans/spring -beans.xsd">
<import resource="bean1.xml"/import>
<import resource="bean2.xml"></import>
<import resource="beans xml"></import>
</beans>
5、DRUID连接池【掌握】
常用连接池技术:DBCP、C3PO、Proxool、Druid
1 )在pom.xml文件中添加组件依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/druid -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.22</version>
</dependency>
2)代码
<bean id="dataSources" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
<property name="url" value="jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8"></property>
<property name="username" value="root"></property>
<property name="password" value="123456"></property>
<!--数据连接池初始化数-->
<property name="initialSize" value="15"></property>
<!-- 最小连接池数量-->
<property name="minIdle" value="5"/>
<!--最大连接数据库连接数-->
<property name="maxActive" value="100"/>
<!--最大等待毫秒数-->
<property name="maxWait" value="6000"/>
</bean>
测试
@Test
public void testDataSource() throws SQLException {
ApplicationContext context= new ClassPathXmlApplicationContext("beans.xml");
DruidDataSource dataSource = (DruidDataSource) context.getBean("dataSources");
logger.info(dataSource.getConnection());
}
6、spring引入外部的properties文件
在spring中引入外部的properties文件的方法有两种
在resources目录下新建datasource.properties文件
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/mydb?useUnicode=true&characterEncoding=UTF8
user=root
password=123456
initialSize=10
minIdle=5
maxActive=100
maxWait=6000
(1)使用PropertyPlaceholderConfigurer引入(不推荐使用)
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="datasource.properties"/>
</bean>
<bean id="dataSources" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${user}"></property>
<property name="password" value="${password}"></property>
<!--数据连接池初始化数-->
<property name="initialSize" value="${initialSize}"></property>
<!-- 最小连接池数量-->
<property name="minIdle" value="${minIdle}"/>
<!--最大连接数据库连接数-->
<property name="maxActive" value="${maxActive}"/>
<!--最大等待毫秒数-->
<property name="maxWait" value="${maxWait}"/>
</bean>
2)使用context:property-placeholder引入
<?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.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:property-placeholder location="datasource.properties"/>
<bean id="dataSources" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="${driver}"></property>
<property name="url" value="${url}"></property>
<property name="username" value="${user}"></property>
<property name="password" value="${password}"></property>
<!--数据连接池初始化数-->
<property name="initialSize" value="${initialSize}"></property>
<!-- 最小连接池数量-->
<property name="minIdle" value="${minIdle}"/>
<!--最大连接数据库连接数-->
<property name="maxActive" value="${maxActive}"/>
<!--最大等待毫秒数-->
<property name="maxWait" value="${maxWait}"/>
</bean>
</beans>
使用qontext:property-placeholder的时候出现引用不来情况
原因是∶由于properties内username和系统环境的username重名导致的,解决办法有两种
第1种∶不要在配置文件中出现username这样的key,重新取个名称,一般有一个习惯给前面带jdbc前缀例如
jdbc. driver=com.aysql.jdbc. Driver
jdbc.url=jdbc:nysql://localhost:3306/nybatis?useUnicode=truekcharacterEncoding-utf8
jdbc.usernane=root
jdbc. password=1234
第2种∶在property-placeholder>中加入system-properties-mode="FALLBACK”也可以解决这个问题
七、SpringAOP
—.代理
**代理分为:**静态代理 、动态代理
代理模式∶目标对象,增强部分的内容
**什么是代理:**代理模式 ( Proxy )是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能。

1.静态代理的实现
2.动态代理的实现
JDK的动态代理,使用了Proxy中的静态方法newProxyInstance,该方法有三个参数
· ClassLoader loader:目标对象的类加载器
本文介绍了Spring框架的核心概念和优势,包括控制反转IoC和面向切面编程AOP,以及Spring的预设知识,如BeanFactory和ApplicationContext。通过一个简单的入门程序展示了Spring的配置过程。进一步探讨了Spring的核心容器、IOC和DI的理解,强调了依赖注入的重要性。文章还涵盖了Spring中Bean的实例化、作用域和生命周期管理,并讨论了Spring配置文件的拆分、Druid连接池的使用以及如何引入外部properties文件。最后,简要提及了Spring的代理和动态代理实现。
1万+

被折叠的 条评论
为什么被折叠?



