尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

自学SSM+springboot day1

自学SSM+springboot day1 今天主要学习Spring的核心知识。一、Spring是什么Spring 是一个开源的 Java 应用开发框架核心目的是简化企业级 Java 应用的开发。它最核心的两个功能是IoC也就是控制反转以及AOP也就是面向切面编程。除此之外Spring 还提供了事务管理、Web 开发、数据访问等能力并且形成了一个完整的生态。二、Spring系统架构三、核心概念IoC控制反转IoCInversion of Control控制反转:使用对象时由主动new对象转换为由外部提供对象此过程中对象创建控制权由程序转移到外部此思想称为控制反转。Spring技术对IoC思想进行了实现Spring提供了一个容器成为IoC容器用来充当IoC思想中的“外部”。也就是说由IoC容器提供对象。IoC容器则负责对象的创建、初始化等一系列工作被创建或被管理的对象在IoC容器中统称为Bean。DI依赖注入DIDependency Injection依赖注入在容器中建立bean与bean之间的依赖关系的整个过程称为依赖注入。目标及最终效果目标充分解耦使用IoC容器管理beanIoC在IoC容器内将有依赖关系的bean进行关系绑定DI最终效果使用对象时不仅可以直接从IoC容器中获取并且获取到的bean已经绑定了所有的依赖关系四、IoC入门案例IoC入门案例思路及分析1.管理什么Service与Dao2.如何将被管理的对象告知IoC容器配置3.被管理的对象交给IoC容器如何获取到IoC容器接口4.IoC容器得到后如何从容器中获取bean接口方法5.使用Spring导入哪些坐标pom.xml代码不重要后续不用这个方法了。五、DI入门案例DI入门案例思路及分析1.基于IoC管理bean2.Service中使用new形式创建的Dao对象是否保留否3.Service中需要的Dao对象如何进入到Service中提供对应的Set方法4.Service与Dao间的关系如何描述配置六、bean的核心知识bean的基础配置bean别名配置bean作用范围配置适合交给容器管理的bean表现层对象业务层对象数据层对象工具对象不适合交给容器进行管理的bean封装实体的域对象bean实例化的三种方式构造方法常用bean本质上就是对象创建bean使用构造方法完成提供可访问的构造方法public class BookDaoImpl implements BookDao{ public BookDaoImpl(){ System.out.println(book constructor is running ...); } public void save(){ System.out.println(book dao save ...); } }配置bean idbookDao classcom.itheima.dao.impl.BookDaoImpl /无参构造方法如果不存在将抛出异常BeanCreationException。静态工厂了解即可静态工厂public class OrderDaoFactory{ public static OrderDao getOrderDao(){ return new OrderDaoImpl(); } }配置bean idorderDao factory-methodgetOrderDao classcom.itheima.factory.OrderDaoFactory /实例工厂了解即可实例工厂public class UserDaoFactory{ public UserDao getUserDao(){ return new UserDaoImpl(); } }配置bean iduserDaoFactory classcom.itheima.factory.UserDaoFactory/ bean iduserDao factory-methodgetUserDao factory-beanuserDaoFactory//这里和上一行的id相同 /FactoryBean(实用)public class UserDaoFactoryBean implements FactoryBeanUserDao{ public UserDao getObject() throws Exception{ return new UserDaoImpl(); } public Class? getObjectType(){ return UserDao.class; } }配置bean iduserDao classcom.itheima.factory.UserDaoFactoryBean /bean的生命周期提供生命周期控制方法public class BookDaoImpl implements BookDao{ public void save(){ System.out.println(book dao save ...); } public void init(){ System.out.println(book init ...); } public void destory(){ System.out.println(book destory ...); } }配置生命周期控制方法bean idbookDao classcom.itheima.dao.impl.BookDaoImpl init-methodinit destroy-methoddestory /初始化容器创建对象内存分配执行构造方法执行属性注入set操作执行bean初始化方法使用bean执行业务操作关闭/销毁容器执行bean销毁方法bean销毁时机容器关闭前触发bean的销毁关闭容器的方式手工关闭容器ConfigurableApplicationContext接口close()操作注册关闭钩子在虚拟机退出前先关闭容器再退出虚拟机ConfigurableApplicationContext接口registerShutdownHook()操作public class AppForLifeCycle{ public static void main(String[] arge){ ClassPathXmlApplicationContext ctx new ClassPathXmlApplicationContext(applicationContext.xml); ctx.close(); } }七、依赖注入方式setter注入在bean中定义引用类型属性并提供可访问的set方法public class BookDaoImpl implements BookDao{ private int connectionNumber; public void setConnectionNumber(int connectionNumber){ this.connectionNumber connectionNumber; } }配置中使用property标签value属性注入简单类型数据bean idbookDao classcom.itheima.dao.impl.BookDaoInpl property nameconnectionNumber value10 / /bean构造器注入在bean中定义引用类型属性并提供可访问的set方法public class BookDaoImpl implements BookDao{ private int connectionNumber; public void setConnectionNumber(int connectionNumber){ this.connectionNumber connectionNumber; } }配置中使用constructor-arg标签value属性注入简单类型数据bean idbookDao classcom.itheima.dao.impl.BookDaoImpl constructor-arg nameconnectionNumber value10/ /bean配置中使用constructor-arg标签type属性注入简单类型数据bean idbookDao classcom.itheima.dao.impl.BookDaoImpl constructor-arg typeint value10/ constructor-arg typejava.lang.String valuemysql/ /bean配置中使用constructor-arg标签index属性注入简单类型数据bean idbookDao classcom.itheima.dao.impl.BookDaoImpl constructor-arg index0 value10/ constructor-arg index1 valuemysql/ /bean依赖注入方式选择1.强制依赖使用构造器进行使用setter注入有概率不进行注入导致null对象出现2.可选依赖使用setter注入进行灵活性强3.Spring框架倡导使用构造器第三方框架内部大多数采用构造器注入的形式进行数据初始化相对严谨4.如果有必要可以两者同时使用使用构造器注入完成强制依赖的注入使用setter注入完成可选依赖的注入5.实际开发过程中还要根据实际情况分析如果受控对象没有提供setter方法就必须使用构造器注入6.自己开发的模块推荐使用setter注入依赖自动装配IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配。自动装配方式使用Aotuwire标签自动装配自动装配用于引用类型依赖注入不能对简单类型进行操作按类型常用byType必须保障容器中相同类型的bean唯一推荐使用。按名称:byName必须保障容器中具有指定名称的bean因变量名与配置耦合不推荐使用。按构造方法不启用自动装配自动装配优先级低于setter注入与构造器注入同时出现自动装配配置失效。注入集合对象注入数组对象property namearray array value100/value value200/value value300/value /array /property注入List对象重点property namelist list valueitheima/value valueitcast/value valueboxuegu/value /list /property注入Map对象重点property namemap map entry keycountry valuechina / entry keyprovince valuehenan / entry keycity valuekaifeng / /map /property注入Properties对象property nameproperties props prop keycountrychina/prop prop keyprovincehenan/prop prop keycitykaifeng/prop /props /property加载properties文件八、容器创建容器方式一类路径加载配置文件ApplicationContext ctx new ClassPathXmlApplicationContext(applicationContext.xml);方式二文件路径加载配置文件ApplicationContext ctx new FileSystemXmlApplicationContext(D://applicationContext.xml);加载多个配置文件ApplicationContext ctx new ClassPathXmlApplicationContext(bean1.xml,bean2.xml);获取bean方式一使用bean名称获取BookDao bookDao (BookDao) ctx.getBean(bookDao);方式二使用bean名称获取并制定类型BookDao bookDao ctx.getBean(bookDao,BookDao.class);方式三使用bean类型获取BookDao bookDao ctx.getBean(BookDao.class);容器类层次结构图BeanFactory初始化九、注解开发注解开发定义bean使用Component定义beanComponent(bookDao) public class BookDaoImpl implements BookDao{ } Component public class BookServiceImpl implements BookService{ }核心配置文件中通过组件扫描加载beancontext:component-scan base-packagecom.itheima/Spring提供Component注解的三个衍生注解Controller:用于表现层bean定义Service:用于业务层bean定义Repository:用于数据层bean定义Repository(bookDao) public class BookDaoImpl implements BookDao{ } Service public class BookServiceImpl implements BookService{ }纯注解开发Spring3.0开启了纯注解开发模式使用Java类替代配置文件开启了Spring快速开发通道Java类代替Spring核心配置文件Configuration ComponentScan(com.itheima) public class SpringConfig{ }Configuration注解用于设定当前配置类ComponentScan注解用于设定扫描路径此注解只能添加一次多个数据请用数组格式ComponentScan({com.itheima.service,com.itheima.dao})读取Spring核心配置文件初始化容器对象切换为读物Java配置类初始化容器对象//加载配置文件初始化容器 ApplicationContext ctx new ClassPathXmlApplicationContext(applicationContext.xml); //加载配置类初始化容器 ApplicationContext ctx new AnnotationConfigApplicationContext(SpringConfig.class);bean的管理bean的作用范围使用Scope定义bean作用范围Repository Scope(singleton) public class BookDaoImpl implements BookDao{ }bean的生命周期使用PostConstruct、PreDestroy定义生命周期Repository Scope(singleton) public class BookDaoImpl implements BookDao{ public BookDaoImpl(){ System.out.println(book dao constructor ...); } PostConstruct public void init(){ System.out.println(book init ...); } PreDestroy public void destroy(){ System.out.println(book destroy ...); } }依赖注入自动装配使用Autowired注解开启自动装配模式按类型Serviec public class BookServiceImpl implements BookService{ Autowired Qualifier(bookDao)//指定名称装配bean private BookDao bookDao; // public void setBookDao(BookDao bookDao){ // this.bookDao bookDao; // } public void save(){ System.out.println(book service save ...); bookDao.save(); } }注意自动装配基于反射设计创建对象并暴力反射对应属性为私有属性私有化数据因此无需提供setter方法注意自动装配建议使用无参构造方法创建对象默认如果不提供对应构造方法请提供唯一的构造方法注意Qualifier注解无法单独使用必须配合Autowired注解使用使用Value实现简单类型注入Repository public class BookDaoImpl implements BookDao{ Value(100) private String connectionNum; }加载properties文件使用PropertySource注解加载properties文件Configuration ComponentScan(com.itheima) PropertySource(classpath:jdbc.properties) public class SpringConfig{ }注意路径仅支持单一文件配置多文件请使用数组格式配置不允许使用通配符*第三方bean管理使用Bean配置第三方beanConfiguration public class SpringConfig{ Bean public DataSource dataSource(){ DruidDataSource ds new DruidDataSource(); ds.setDriverClassName(com.mysql.jdbc.Driver); ds.setUrl(jdbc:mysql://localhost:3306/spring_db); ds.setUsername(root); ds.setPassword(root); return ds; } }将独立的配置类加入核心配置导入式public class jdbcConfig{ Bean public DataSource dataSource(){ DruidDataSource ds new DruidDataSource(); ds.setDriverClassName(com.mysql.jdbc.Driver); ds.setUrl(jdbc:mysql://localhost:3306/spring_db); ds.setUsername(root); ds.setPassword(root); return ds; } }使用Import注解手动加入配置类到核心配置此注解只能添加一次多个数据请用数组格式Configuration Import(JdbcConfig.class) public class SpringConfig{ }第三方bean依赖注入简单类型依赖注入public class jdbcConfig{ Value(com.mysql.jdbc.Driver) private String driver; Value(jdbc:mysql://localhost:3306/spring_db) private String url; Value(root) private String userName; Value(root) private String password; Bean public DataSource dataSource(){ DruidDataSource ds new DruidDataSource(driver); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }引用类型依赖注入Bean public DataSource dataSource(BookService bookService){ System.out.println(bookService); DruidDataSource ds new DruidDataSource(); //属性设置 return ds; }引用类型注入只需要为bean定义方法设置形参即可容器会根据类型自动装配对象总结十、Spring整合MyBatis将配置文件替换成如下图十一、Spring整合JUnit十二、AOPAOP简介AOP面向切面编程一种编程范式指导开发者如何组织程序结构作用在不惊动原始设计的基础上为其进行功能增强Spring理念无入侵式/无侵入式AOP核心概念连接点程序执行过程中的任意位置粒度为执行方法、抛出异常、设置变量等在SpringAOP中理解为方法的执行切入点匹配连接点的式子在SpringAOP中一个切入点可以只描述一个具体方法也可以匹配多个方法。一个具体方法com.itheima.dao包下的BookDao接口中的无形参无返回值的save方法匹配多个方法所有的save方法所有的get开头的方法所有以Dao结尾的接口中的任意方法所有带有一个参数的方法。通知在切入点处执行的操作也就是共性功能在SpringAOP中功能最终以方法的形式呈现。通知类定义通知的类。切面描述通知与切入点的对应关系。目标对象原始功能去掉共性功能对应的类产生的对象这种对象是无法直接完成最终工作的代理目标对象无法直接完成工作需要对其进行功能回填通过原始对象的代理对象实现AOP入门案例步骤1.导入aop相关坐标dependency groupIdorg.aspectj/groupId artifactIdaspectjweaver/artifactId version1.9.4/version /dependency2.定义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 updata(){ System.out.println(book dao updata ...); } }3.定义通知类制作通知public class MyAdvice{ public void before(){ System.out.println(System.currentTimeMillis()); } }4.定义切入点public class MyAdvice{ Pointcut(execution(void com.itheima.dao.BookDao.update())) private void py(){} }说明切入点定义依托一个不具有实际意义的方法进行即无参数无返回值方法体无实际逻辑5.绑定切入点与通知关系并指定通知添加到原始连接点的具体执行位置public class MyAdvice{ Pointcut(execution(void com.itheima.dao.BookDao.update())) private void pt(){} Before(pt()) public void before(){ System.out.println(System.currentTimeMillis()); } }6.定义通知类受Spring容器管理并定义当前类为切面类Component Aspect public class MyAdvice{ Pointcut(execution(void com.itheima.dao.BookDao.update())) private void pt(){} Before(pt()) public void before(){ System.out.println(System.currentTimeMillis()); } }7.开启Spring对AOP注解驱动支持Configuration ComponentScan(com.itheima) EnableAspectJAutoProxy public class SpringConfig{ }AOP工作流程1.Spring容器启动2.读取所有切面配置中的切入点Component Aspect public class MyAdvice{ Pointcut(execution(void com.itheima.dao.BookDao.save())) private void ptx(){} Pointcut(execution(void com.itheima.dao.BookDao.update())) private void pt(){} Before(pt()) public void before(){ System.out.println(System.currentTimeMillis()); } }3.初始化bean判定bean对应的类中的方法是否匹配到任意切入点匹配失败创建对象匹配成功创建原始对象目标对象的代理对象4.获取bean执行方法获取bean调用方法并执行完成操作获取的bean是代理对象时根据代理对象的运行模式运行原始方法与增强的内容完成操作AOP切入点表达式切入点表达式标准格式动作关键字访问修饰符 返回值 包名.类名/接口名.方法名参数异常名execution(public User com.itheima.service.UserService.findById(int))动作关键字描述切入点的行为动作例如execution表示执行到指定切入点访问修饰符publicprivate等可以省略返回值包名类/接口名方法名参数异常名方法定义中抛出指定异常可以省略可以使用通配符描述切入点快速描述*单个独立的任意符号可以独立出现也可以作为前缀或者后缀的匹配符出现execution(public * com.itheima.*.UserService.find*(*))匹配com.itheima包下的任意包中的UserService类式接口中所有find开发的带有一个参数的方法..多个连续的任意符号可以独立出现常用于简化包名与参数的书写execution(public User com..UserService.findById(..))匹配com包下的任意包中的UserService类或接口中所有名称为findById的方法专用于匹配子类类型execution(* *..*Service.*(..))AOP通知类型AOP通知描述了抽取的共性功能根据共性功能抽取的位置不同最终运行代码时要将其加入到合理的位置AOP通知共分为5种类型前置通知Before后置通知After环绕通知重点AroundAround(pt()) public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println(around before advice..); Object ret pjp.proceed(); System.out.println(around after advice..); return ret; }返回后通知了解:AfterReturning抛出异常后通知了解:AfterThrowingAOP通知获取数据获取参数数据JoinPoint对象描述了连接点方法的运行状态可以获取到原始方法的调用参数Brfore(pt()) public void before(JoinPoint jp){ Object[] args jp.getArgs(); System.out.println(Arrays.toString(args)); }ProceedJoinPoint是JoinPoint的子类Around(pt()) public Object around(ProceedingJoinPoint pjp) throws Throwable{ Object[] args pjp.getArgs(); System.out.printlm(Arrays.toString(args)); Object ret pjp.proceed(); return ret; }获取返回值数据抛出异常后通知可以获取切入点方法中出现的异常信息使用形参可以接收对应的异常对象AfterReturning(valuept(),returningret) public void afterReturning(String ret){ System.out.println(afterReturning advice ...ret); }环绕通知中可以手工书写对原始方法的调用得到的结果即为原始方法的返回值Around(pt()) public Object around(ProceedingJoinPoint pjp) throws Throwable{ Object ret pjp.proceed(); return ret; }十三、Spring事务事务简介事务作用在数据层保障一系列的数据库操作同成功同失败Spring事务作用在数据层或业务层保障一系列的数据库操作同成功同失败开启Spring事务步骤1.在业务层接口上添加Spring事务管理public interface AccountService{ Transactional public void transfer(String out,String in,Double money); }Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中降低耦合注解式事务可以添加到业务方法上表示当前方法开启事务也可以添加到接口上表示当前接口所有方法开启事务。2.设置事务管理器Bean public PlatfromTransactionManager transactionManager(DataSource dataSource){ DataSourceTransactionManager ptm new DataSourceTransactionManager(); ptm.setDataSource(dataSource); return ptm; }事务管理器要根据实现技术进行选择MyBatis框架使用的是JDBC事务。3.开启注解式事务驱动Configuration ComponentScan(com.itheima) PropertySource(classpath:jdbc.properties) Import({JdbcConfig.class,MybatisConfig.class}) EnableTransactionManagement public class SpringConfig{ }Spring事务角色事务管理员发起事务方在Spring中通常指代业务层开启事务的方法事务协调员加入事务方在Spring中通常指代数据层方法也可以是业务层方法事务相关配置在业务层接口上添加Spring事务设置事务传播行为REQUIRES_NEW(需要新事务)Service public class LogServiceImpl implements LogService{ Autowired private LogDao logDao; Transactional(propagation Propagation.REQUIRES_NEW) public void log(String out,String in,Double money){ logDao.log(转账操作由out到in金额money); } }事务传播行为事务协调员对事务管理员所携带事物的处理态度
返回列表