最近在学一些后端的技术，零零散散记了一些相关的知识点，有关Spring的内容基本就集中在这一篇。看的教程网址：教程链接Spring核心概念IoC(Inversion of Control)控制反转使用对象时，由主动的new来产生对象转变为外部提供对象，此过程中对象创建控制权由程序转移到外部Spring提供一个容器IoC容器来充当“外部"这个容器复杂对象的创建、初始化等一系列工作，被创建或被管理的对象在IoC容器中统称为Bean目标：充分解耦使用IoC管理Bean(IoC)在IoC容器中将有依赖关系的bean进行关系绑定(DI)IoC思路分析IoC管理Service和Dao用配置将被管理的对象告知IoC容器用接口获取IoC容器用接口方法从容器中获取Bean1）导入spring坐标2）定义Spring管理的类(接口)3）创建Spring配置文件，配置对应的类作为Spring管理的Bean 注意：bean定义时id属性在同一个上下文中不能重复DI入门案例依赖注入，全称 Dependency Injection，简称 DI依赖关系的维护就称为依赖注入基于IoC管理BeanService中使用new形式创建的对象不能保留Service中需要的Dao对象通过方法进入Service中1）删除使用new形式创建对象的代码2）提供依赖对象对应的set方法3）配置service和dao之间的关系 BeanBean基础配置标签id:bean的id，使用容器可以通过id值获取对应的bean，在一个容器中id值唯一class:bean的类型，即配置的bean的店路径名name:bean的别名，可以使用空格分隔多个别名scope:作用范围，可以选择单例或者多例，默认单例适合交给容器进行管理的Bean表现层对象业务层对象数据层对象工具对象Controller:控制层，接受前端发送的请求，对请求进行处理，并响应数据Service:业务逻辑层，处理具体的业务逻辑Dao:数据访问层，复杂数据访问操作，包括数据的增删改查Bean实例化实例化Bean的方式用构造方法(无参)创建对象，如果没有无参构造方法将抛出异常BeanCreationException静态工厂实例化Bean， 实例工厂初始化Bean 可以使用接口FactoryBean<>来代替public class UseDaoFactoryBean implements FactoryBean<UserDao>{ public UserDao getObject() throws Exception{ return new UserDaoImpl(); } public Class<> getObjectType(){ reuturn UserDao.class; } }配置 Bean的生命周期生命周期：从创建到销毁的完整过程初始化容器创建对象执行构造方法执行属性注入(set)执行bean初始化方法使用bean关闭/销毁容器执行bean销毁方法bean的生命周期控制：在bean创建后到销毁前做一些事情加载properties文件开启context命名空间<? xml version="1.0" encoding="UTF-8"?> < beans xmlns=" http://www.springframework.org/schema/bean s" 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 "> </ beans>使用contex命名空间<context:property-placeholder locaion=" "/>使用${}读取加载的属性值 不加载系统属性<context:property-placeholder location="" system-properties-mode="NEVER"/>加载多个properties文件<context:property-placeholder location="jdbc.properties.msg.properties"/>加载所有properties文件<context:property-placeholder location="*.properties"/>标准格式<context:property-placeholder location="classpath:*.properties"/>从类路径或jar包中搜索并加载properties文件<context:property-placeholder location="classpath*:*.properties"/>依赖注入向一个类传递数据的方式普通方法(set方法)构造方法bean运行需要的数据类型可以简单地分成两大类引用类型简单类型(基本数据类型与String)Setter注入引用类型在bean中定义引用类型属性并提供可访问地set方法public class BookServiceImpl implements BookService{ private BookDao bookDao; public void setBookDao(BookDao bookDao){ this.bookDao = bookDao; } }配置中使用property标签ref属性注入引用对象 简单类型在bean中定义引用类型属性并提供可访问地set方法public class BookDaoImpl implements BookDao{ private int connectionNumber; public void setConnectionNumber(int connectionNumber){ this.connectionNumber = connectionNumber; } }配置中使用property标签value属性注入引用对象 构造方法注入引用类型public class BookServiceImpl implements BookService{ private int connectionNumber; public BookServiceImpl(BookDao bookDao){ this.bookDao=bookDao; } } <constructor-arg name="形参的名称" ref="bookDao"/> 简单类型 <constructor-arg name="形参的名称" value="xxx"/> 但是依然有耦合，另外一种写法type中写对应参数的类型，解决形参名的问题 <constructor-arg type="java.lang.String" value="xxx"/> index写参数的位数，第0个，第1个...解决参数类型重复的问题 <constructor-arg index="0" type="java.lang.String" value="xxx"/> 依赖注入方式的选择强制依赖：bean运行必须的依赖强制依赖使用构造器进行，使用setter注入又改了不进行注入导致null对象出现可选以来用setter注入，灵活Spring框架倡导使用构造器，第三方框架内部大多采用构造器注入的形式进行初始化如有必要可以两者同时使用，使用构造器注入完成强制依赖输入，setter注入完成可选依赖注入实际开发时要根据实际情况分析，如果受控对象没有提供setter方法就必须使用构造器注入自己开发的模块推荐使用setter注入依赖自动装配IoC容器根据bean所以来的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式按类型(常用)按名称按构造方法autowire标签后面可以选择不同的方式使用byType，如果存在多个bean类型相同会报错，此时可以使用byName 提示自动装配用于引用类型依赖注入，不能对简单类型进行操作使用按类型装配(byType)必须保证容器中相同类型的bean唯一使用按名称装配(byName)必须保证容器中右指定名称的bean，但是资源变量名与配置会耦合自动装配优先级低于setter注入和构造器注入，提示出现时自动装配配置失效集合注入数组 List Set Map Propertiesname属性后面是变量名，和类型无关 100 200 ahsoi sakjahfkj ahsoi sakjahfkj <entry key="country" value="china"/> china 注解开发使用注解配置bean@Component("bean名称")要在核心配置文件中通过组件扫描加载bean<context:component-scan base-package=" "/>业务层的bean建议使用@Service数据层使用@Respository表现层使用@Controller纯注解开发用类来代替配置文件，使用注解@Configuration(设定当前类为配置类)用注解@ComponentScan("")来设定扫描路径，次注解只能加一次//转换前 ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml") //转换后，写的是配置类的名称 ApplicationContext ctx = new ClassPathXmlApplicationContext(SpringConfig.class)bean管理bean作用范围@Scope注解bean生命周期@PostConstruct注解，表示在构造方法后运行@PreDestroy注解，表示在销毁前运行注解开发依赖注入自动装配@Autowired注解，可以把set方法去掉如果有两个相同类型bean的数据层实现要用名称指定@Qualifier("名称")+@Autowired(前者必须配合后者使用)注：自动装配基于反射设计创建对象并暴力发射对应属性为私有属性初始化数据，无需提供setter方法自动装配建议使用无参构造方法创建对象简单类型注入使用@Value("值")注解@Value("sjdh") private String name;可以从properties文件中加载配置，需要在对应的Config类里面加上@PropertySource注解@Configuration @ComponentScan("...") //不能使用通配符* @PropertySource("xxx.properties") public class Config(){ }第三方bean管理需要手动获得管理对象public class SpringConfig{ //定义一个方法要管理的对象 //添加注解，表示返回值是bean @Bean public DataSource datasource(){ DruidDataSource ds=new DruidDataSource(); ds.setDriverClassName(" "); return ds; } }方式一：导入式public class SpringConfig{ //定义一个方法要管理的对象 //添加注解，表示返回值是bean @Bean public DataSource datasource(){ } }使用@Import主角儿手动加入配置类到核心配置，只能添加一次@Configuration @Import() public class SpringConfig{ }方式二：扫描式(不建议)第三方bean依赖注入引用类型注入只需要为bean定义方法设置形参即可，容器会根据类型自动装配对象@Bean public DataSource dataSource(BookService bookService){ System.out.println(bookService); DruidDataSource ds = new DruidDataSource(); return ds; }AOPAOP核心概念AOP(Aspect Oriented Programming)面向切面编程，一种编程范式，指导开发者如何组织程序结构作用：在不动原始设计的基础上增强功能Spring理念：无入侵式抽取出来的方法称为连接点，要追加功能的方法称为切入点，共性功能称为通知，用切面描述通知与切入点的关系还要有通知类，连接点式所有方法，切入点是匹配某些方法连接点(JoinPoint)：程序执行过程中的任意位置在SpringAOP中理解为方法的执行切入点(Pointcut)：匹配连接点的式子通知(Advice)：在切入点处执行的操作，也就是共性功能切面(Aspect)：描述通知与切入点的对应关系AOP思路将坐标导入pom.xml文件 org.aspectj aspectjweaver 1.9.4 制作连接点方法（原始操作，Dao接口与实现类）public interface BookDao{ public void save(); public void update(); }@Repository public class BookDaoImpl implements BookDao{ public void save(){ System.out.println(System.currentTimeMillis()); System.out.println("book dao save ... "); } public void update(){ System.out.println("book dao update ... "); } }定义通知类public void MyAdvice{ public void before(){ System.out.println(System.currentTimeMillis()); } }定义切入点@Pointcut注解public void MyAdvice{ @Pointcut("executio()") private void pt(){} public void before(){ } }绑定切入点与通知关系（切面）public void MyAdvice{ @Pointcut("execution()") @Before("pt()") public void before(){ } }定义通知类受Spring管理，并定义当前类为切面类要使用@Aspect和@Component注解AOP工作流程Spring容器启动读取所有切面配置中的切入点初始化bean，判顶对应的类中的方法是都撇皮到任意切入点​ 如果匹配失败则创建对象​ 匹配成功，创建目标对象的代理对象获取bean执行方法​ 获取bean，调用方法并执行，完成操作​ 获取的bean式代理对象时，根据代理对象的运行模式运行原始方法与增强的内容，完成操作目标对象原始功能去掉共性功能对应的类产生的对象，这种对象无法直接完成最后的工作代理目标对象无法直接完成工作，需要对其进行功能回填，通过原始对象的代理对象实现AOP切入点表达式切入点：要进行增强的方法切入点表达式：要进行增强的方法的描述方式描述方式一：执行该路径下BookDao接口中的无参数update方法execution(void.com.it.dao.BookDao.update())描述方法二：执行impl包下的BookDaoImpl类中的无参数update方法execution(void com.it.dao.impl.BookDaoImpl.update())切入点表达式标准动作关键字（访问修饰符 返回值 包名.类/接口名.方法名(参数)异常名）可以使用通配符描述切入点*：单个独立的任意符号，可以独立出现，也可以作为前缀或者后缀的匹配符出现execution (public * com. itheima.*. UserService. find* (*))匹配 com. itheima包下的任意包中的UserService类或接口中所有 find开头的带有一个参数的方法..：多个连续的任意符号，可以独立出现，常用于简化包名与参数的书写execution (public User com.. UserService. findById (..))匹配 com包下的任意包中的UserService类或接口中所有名称为findByld的方法+：专用于匹配子类型execution(*..* Service+.*(..))书写技巧描述切入点通常描述接口，而不描述实现类包名书写尽量不使用..匹配方法名书写档次以进行精准匹配通常不使用异常作为匹配接口名/类名书写名称与模块相关的采用*匹配AOP通知类型分类前置通知@Before("")后置通知@After("")环绕通知@Around("")返回后通知@AfterReturning抛出异常后通知@AfterThrowing@Around注意事项环绕通知必须依赖形参ProceedingJoinPoint才能实现对原始方法的调用，进而实现原始方法调用前后同时添加通知如果未使用ProceedingJoinPoint对原始方法进行调用将跳过原始方法的执行如果对原始方法接受返回值，设置成Object类型环绕通知方法必须抛出Throwable对象AOP通知获取数据获取切入点方法的参数JoinPoint：适用于前置，后置，返回后、抛出异常后通知@Berfore() public void before(JoinPoint jp){ Object[] args=jp.getArgs(); }ProceedJointPoint：适用于环绕通知，是JoinPoint的子类获取切入点方法返回值返回后通知@AfterReturning(value="",retyrning="形参名")环绕通知获取切入点方法运行异常异常抛出异常后通知环绕通知Spring事务作用：在数据层或业务层保障一系列的数据库操作痛失败痛成功通过PlatformTransactionManager接口实现里面有commit和rollback方法在业务层接口上添加Spring事务管理@Transactional注解(通常添加在业务层接口而不是业务层实现类)设置事务管理器(JDBC事务，根据实际情况选择)@Bean public PlatformTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager ptm = new DataSourceTransactionManager(); ptm.setDataSource(dataSource); return ptm; }开启注解式事务驱动在SpringConfig类上添加@EnableTransactionManagement注解事务角色事务管理员：发起事务方，在Spring中通常指代业务层开启事务的方法事务协调员：加入事务方，在Spring中通常指代数据层方法，也可以是业务层方法事务属性事务相关配置readOnly，rollbackFor等