Spring4学习笔记

一、本节重点:
1、ioc控制反转
2、di依赖注入

1、spring的介绍
1)spring理解:
spring是一个对象的容器,专门来管理对象。
spring是一站式轻量级的框架,一站式具体表现在spring自己可以实现表现层、业务层、持久层分层功能。
2)spring有三大经典的思想,分别是"IOC"、"DI"、"AOP"(面试笔试必问)

2、IOC(inversion of controller)控制反转
1)IOC的理解
Student st=new Student("",18);
现在,一个对象的创建和整个生命周期的维护都交给了spring,
通过配置文件或者注解的方式来解决对象的产生

2)IOC入门案例体会
    (1)ioc底层实现原理(反射+工厂模式)
    (2)ioc实现的步骤
        第一步:导入基本的jar(beans,context,core,expression,日志包)
        第二步:在src目录下创建spring创建bean的配置文件(引入约束,配置bean)
        第三步:使用ClassPathXmlApplicationContext测试,从spring中获取bean
        ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
        User user=(User)context.getBean("user");
        
3)spring创建bean的三种方式(重点掌握无参构造来实例化对象)
    (1)无参构造(默认,实际开发中使用该方法)
    (2)静态工厂类,静态工厂方法
    (3)普通工厂类,普通实例工厂方法
    

3、DI(dependency injection)依赖注入
1)DI的理解(对象的成员变量初始化)
给bean的成员变量初始化,该成员变量可以是一个普通的类型,也可以是一个引用类型变量。

2)DI实现的3种方式
    (1)set方法注入(最常用)
        在Bean所在类中提供成员变量的set方法
        在Spring的配置文件中使用 
            
    (2)有参构造注入
        在Bean所在类中提供成员变量的有参构造
        在spring的配置文件中使用
        
            
            
        
        
    (3)使用set方法注入对象、集合、数组、properties数据
        a. 将已经声明的对象可以通过ref属性引入 
        b. 注入数组或者list
        c. 注入map
        d.  注入properties属性
       
        数组:在CollectionDemo里面private Object[] objectArray; 提供get/set方法
              在applicationContext.xml中配置与list一样
              取值:objectArray[2]
       
3)使用场景:如果该类中成员变量需要通过配置文件静态设置参数可以,使用注入的方法进行初始化
    如:配置jdbc中的数据源可以设置数据库连接账号密码等属性;(在开发中非常常见)
    如:一些类"关联"了其他对象,可以通过依赖注入的set方法,ref=""(在开发中非常常见)
    注意:ref=""往往需要将已经交给spring管理的bean进行引用
    
4)spel:spring的表达式
   #{person.age}     
   #{person.getAge()}

====================================================================================================================================
1、注解开发实现ioc以及DI注入(重点掌握)
1)注解实现ioc
需要导入aop的包,并在xml中将context的命名空间加入
(每一个人必须会说)扫描包下所有带有组件注解的类
@Component后面衍生为@Controller(web) @Service(service) @Repository(dao) 表明当前类是组件类

2)注解实现di
    @Value("张三") 直接给普通类型去赋值,掌握,后面会结合properties文件来使用
    @Autowired 首先是按照类型去寻找  (可以放在成员变量,也可以放在方法)
    @Autowired+@Qualifier= @Resource 
    @Autowired 首先按照类型去找,没有找到就按照名称   
    @Resource  首先按照名称去找,没有找到就按照类型 
    注意:使用注解实现di的时候,引用类型也要交给spring管理

3)其他注解(了解)
    @Scope("singleton/prototype...")等价于
    @PostConstruct等价于 定义的init-method方法 (要求掌握,因为该注解在做一些初始化数据的时候有用,一些项目中用到了)
    @PreDestroy销毁,注意bean的scope=singleton

4)spring和junit4集成的测试(掌握,企业中开发写的controller+service+dao层代码都需要自己单独写测试,才能提交代码)
    @RunWith(SpringJUnit4ClassRunner.class)// spring整合junit4
    @ContextConfiguration(locations = "classpath:applicationContext.xml")   
    
5)在web.xml配置了(ssh整合的时候,我们需要再次回顾体会,现在讲解该知识点只是做铺垫)
    ContextLoaderListener spring的配置文件的地址
    在容器启动的时候,就加载spring的配置文件
    创建所有声明的bean,并完成bean的初始化
    将所有创建完的bean放到ServletContext
    controller/service/dao,去取bean的时候,就是从spring容器中去取
    注意:记住这里的ContextLoaderListener翻译成中文就是上下文加载监听器
    
6)通过xml和注解能不能混合使用?是可以的

1、aop面向切面编程介绍
增强类 目标类
A {
 a(公共的逻辑)
 b(业务逻辑)
 c(公共的逻辑)

当一个方法中执行需要先后执行a,b,c逻辑的时候,我们能不能把a,c逻辑放在一个类中,
给其他类共用?能不能动态组合a+b+c逻辑,这就是面向切面编程思想的来源

底层使用动态代理:jdk和cglib,目标对象有接口,优先采用jdk,没有接口则采用cglib
1)jdk实现动态代理(基于接口实现代理对象)
2)cglib实现动态代理(基于继承父类而实现代理对象,代理对象继承目标对象)
    一个类,有接口,优先jdk,无接口,cglib

2、aop各种概念介绍
1)核心概念:(掌握)
(1)目标类(target): 要被增强的类
(2)代理类(proxy): 使用动态代理产生目标类的代理
(3)切入点(pointcut):目标类中需要增强的方法,这些方法都称为切入点
(4)通知(advice): 增强类中定义的方法,这些方法用于增强目标方法
(5)切面(aspect): 切入点+通知

2)其他概念:(理解)
    (1)连接点(joinpoint):目标类中的所有方法
    (2)织入(weaving): 将通知方法加到目标方法中的过程  spring aop整个过程就是织入
    (3)引入(introduction): 在目标类引入新的属性或者新的方法  了解一下就行    

3、aop之aspectj各种通知(理解)
前置通知 before 目标方法被调用之前,就执行该前置通知方法
后置(最终)通知 after 目标方法被调用完之后,不关心返回结果,就执行该后置通知方法,也叫最终通知
返回通知 after-returning 目标方法return返回之后,就执行该返回通知方法
环绕通知 around 包裹了目标方法,在目标方法之前和在目标方法之后整个过程,经常使用ProceedJoinPoint.proceed()来执行目标方法
异常通知 after-throwing 当目标方法在执行异常的时候,就会执行该异常通知方法

4、通过xml实现spring aop
1)spring传统方式实现aop编程(还沿用了传统的方式,这里只做了解)

id="orderServicePointCut" />

2)spring基于aspectj实现aop编程(重点掌握,今天晚上需要敲代码做实验)
    
         //切面
             //切入点
              //后置通知
            //前置通知
            //环绕通知
             //异常通知
            //返回通知
        
    
    
3)切入点表达式,execution(表达式)
    表达式完整格式:访问修饰符 返回类型 包.类.方法(方法参数)  注意这里的访问修饰符可省略
    * *.*(..) 匹配所有类所有方法  (第一个*代表返回类型)
    * *(..) 匹配所有类所有方法
    * cn.itcast.User.*(..)  匹配User类下面的所有方法
    * cn.itcast..*.*(..) 匹配itcast包下所有子包下的所有方法
    实际开发中,根据情况改变切入点表达式的包和方法
    
4)补充说明applicationContext.xml中标签使用(掌握,实际开发过程中会将配置分门别类进行配置,然后通过import标签引入)
     引入到唯一的一个配置文件中
    分模块开发配置,这样好处就是分门别类,减少耦合性,如下面的配置文件
    applicationContext-jdbc.xml   定义jdbc连接信息
    applicationContext-beans.xml  定义申明的bean
    applicationContext-redis.xml  定义声明redis连接信息

====================================================================================================================================
本节重点:
1、AOP注解编程
2、使用jdbcTemplate实现crud

1、通过注解实现spring aop(重点掌握)
1)打开aop注解开关

aop切面自动代理
2)声明切面类、各种通知
@Component
@Aspect 声明切面类,注意该切面类需要被spring当成component来管理
@Pointcut("execution(* .s(..))") 声明切入点,可以在一个空的方法上声明切入点,然后在其他通知中直接写入空的方法
public void aa(){}
@Before("aa()") 前置通知
@After("aa()") 后置通知,无论出现异常是否,都会调用该通知
@AfterReturning("aa()") 返回通知(企业开发中用的比较多)
@AfterThrowing("aa()") 异常通知
@Around("aa()") 环绕通知(企业开发中用的比较多)
3)2个代表目标方法对象
JoinPoint :获取当前目标类目标方法的所有信息(当前目标类,方法名,方法中的参数)
Object[] objs = joinPoint.getArgs();
ProceedingJoinPoint:只是在环绕通知中使用,它代表了正在执行的目标方法
关于讨论:环绕通知和前置通知以及最终通知的执行顺序,没有价值

2、spring配置连接池(会配)
1)spring内置连接池配置org.springframework.jdbc.datasource.DriverManagerDataSource(了解)
2)spring和c3p0的ComboPooledDataSource配置(掌握)
企业开发中,一般都是把连接数据库的配置放在一个属性文件上,然后引入
两种引入方式:

或者



classpath:db.properties

      通过${}读取属性文件上的配置
    
        
        
        
        
    

3、jdbcTemplate crud操作(重点,要求掌握)
1)需要配置数据源(dataSource)
无论是从C3P0中获取数据源还是从DHCP获取数据源,一般采取的做法是:让spring当成component来管理
2)使用jdbcTemplate核心对象操作数据库
由于JdbcTemplate在实际开发中,经常会使用,所以我们一般会让spring 去管理JdbcTemplate





所以,在dao层,我们可以直接从成员变量中拿到JdbcTemplate对象,然后做crud操作
jdbcTemplate.execute()
添加:jdbcTemplate.update("insert into .. values...")
修改:jdbcTemplate.update("update xx set ")
删除:jdbcTemplate.update("delete from..")
查询:jdbcTemplate.query()/queryForObject()
注意:一些接口如RowMapper(需要重点研究一下),如:
BeanPropertyRowMapper,
PreparedStatementSetter,PreparedStatementCreator等可以课下自己扩展一下,
实际开发中RowMapper用得更多。(启发大家培养自学能力)

4、转账案例的一些问题
注意:JdbcTemplate需要对内部的datasource成员变量进行初始化,
所以JdbcTemplate在交给spring管理时需要首先得提供datasource实现类
转账案例中涉及到几个问题:
1)JdbcDaoSupport
该类就是辅助类,帮助我们的dao层类来完成数据的访问,例如可以获取JdbcTemplate
2)我们能够直接向JdbcDaoSupport中直接注入datasource吗?
org.springframework.jdbc.core.support.JdbcDaoSupport 是一个抽象类,是不能直接被spring利用无参构造来实例化
解决该问题的思路:
如果不能直接,我们通过继承该抽象类来完成实例化工作,通过向子类初始化达到向父类初始化。
向子类初始化成员DriverManagerDataSource或者ComboPooledDataSource
=======================================================================================================================
回顾:
aop编程4种方式:
第一种:最传统的spring aop编程
applicationContext.xml配置目标对象 普通类,里面有方法 连接点,有可能称为切入点
配置通知 实现接口
配置切点 写方法、正则 ".*Order"
配置切面 advice-ref="" pointcut-ref=""
代理类:目标类、切面、指定接口决定用哪种代理方式 jdk、cglib

第二种:传统的spring aop+aspectj的execution表达式写法
    applicationContext.xml配置目标对象
    配置通知 实现接口  def
     //自动生成代理对象
        //切入点
        
        //切面
        
    
    
第三种:整合aspectj框架完成aop编程(重要)
    applicationContext.xml配置目标对象
    配置通知,不需要实现任何接口
      //自动生成代理对象
          //配置切面
            //切点
            
            //通知
            
            
            
            
            
        
    
    
第四种:注解完成aop编程(重要)
    目标对象A
    @Service
    public class A {
    
        public E a(C c,D d,F f) {
            ...
            return new E();
        }
        
    }

    切面类
    @Component
    @Aspect
    public class B{
    
        @Before   //前置通知
        public void a(JoinPoint jp) {
        }
        
        @AfterReturning  //返回通知
        public void b(JoinPoint jp,Object obj) {
            Object[] objs = jp.getArgs(); //可以拿到目标类方法的参数
            obj是目标类方法的返回值
        }

        @Around   //环绕通知
        public void c() {
        }
        
        @AfterThrowing //异常通知
        public void d() {
        }
        
        @After  //后置通知/最终通知
        public void e() {
        }
    
    }
    
    applicationContext.xml配置
    //扫描类上的注解 @Controller @Service @Repository @Component
    
    //开启自动代理
    
    
jdbcTemplate开发环境
导包 c3p0 mysql驱动包 spring-tx spring-jdbc...
applicationContext.xml上c3p0连接池ComboPooledDataSource、jdbcTemplate需要注入dataSource
代码中使用
jdbcTemplate.execute();
jdbcTemplate.update();
jdbcTemplate.query(); /jdbcTemplate.queryForObject(); RowMapper

本节重点:
1、声明式事务的配置
2、ssh框架整合

1.spring事务管理机制(声明式事务,理解)
(1)事务管理器,可以选择相关的平台(jdbc、hibernate、jpa)
org.springframework.transaction.PlatformTransactionManager
包括下面这些:
org.springframework.jdbc.datasource.DataSourceTransactionManager 主要针对于JdbcTemplate、Mybatis开发
org.springframework.orm.jpa.JpaTransactionManager主要针对于JPA开发
HibernateTransactionManager主要针对于Hibernate开发

(2)定义事务的一些特性:隔离、传播、超时、只读
    org.springframework.transaction.TransactionDefinition(可通过docs\javadoc-api/index.html查看)

    隔离:
    ISOLATION_DEFAULT (spring默认采用)
    ISOLATION_READ_COMMITTED 
    ISOLATION_REPEATABLE_READ
    与hibernate讲到的事务隔离级别类似
    2 Read Committed  是oracle默认的隔离级别
    4 Repeatable Read 是mysql默认的隔离级别

    传播:
    两个被事务管理的方法互相调用问题,它与数据库无关,是程序内部维护的问题
    PROPAGATION_REQUIRED(spring默认值) 两个操作处于同一个事务,如果之前没有事务,新建一个事务
    PROPAGATION_REQUIRES_NEW 两个操作处于不同的事务
    PROPAGATION_NESTED 它是一种嵌套事务,只对DataSourceTransactionManager起作用

    a方法和b方法都在事务的管理当中,a方法调用b方法
    a设置为propagation="REQUIRED",b设置为propagation="REQUIRED",a和b在同一个事务里面
        a和b要么同时成功,要么同时失败
    a设置为propagation="REQUIRED",b设置为propagation="REQUIRES_NEW",a和b不在同一个事务里面
        a和b互不影响
    a设置为propagation="REQUIRED",b设置为propagation="NESTED",a所在事务嵌套了b事务,用到了保存点机制
        a可以影响b,但b不能影响a
    保存点:记录出错的方法,便于回滚该方法,默认不开启

(3)事务的状态
    org.springframework.transaction.TransactionStatus

2.spring事务管理(2种方式来配置事务,重点掌握)
xml方式:




    
    
        
            
            
            
            
            
        // propagation、read-only,isolation等属性都是事务默认属性值,可以不用花时间在上面
    

    
    
        
        
        
        
    
        
注解方式:
        
        
            
        
        
        
        
        
        第三步: 在service层类或方法上@Transactional
    
实际开发中,经常要改变可能就是切入点表达式,或者通知属性加上指定的方法

3.依赖注入的总结
(1)xml注入




private B b; 并且提供对应的set方法

(2)注解注入
    
    
    @Autowired
    private B b; //此时无需set方法
    
    xml配置同上,不在属性上加注解,在方法上加
    private B b;
    @Autowired
    public void setB(B b) {  //方法名可以随便写
        this.b = b;
    }
总结:不管是在xml中配置,还是注解,A对象要注入B对象,底层都是调用set方法,给B设置值
    我们自己提供了set方法,就用我们的;如果用注解,不用提供set方法,框架会帮我们生成set方法
    
        
        
    
    
        
        
    

-----------------------------ssh框架整合过程(xml方式)--------------------------------
ssh框架整合的准备工作:
导入struts2、hibernate、spring及相关jar包
web.xml、struts.xml、applicationContext.xml、db.properties、log4j.properties
hibernate.cfg.xml不需要了
1.spring整合hibernate原理+事务配置
第一步:配置数据源ComboPooledDataSource,引入外部属性文件db.properties
第二步:创建LocalSessionFactoryBean来管理hibernate中的SessionFactory
class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
注入连接池
注入hibernate的属性
加载hibernate映射文件XXX.hbm.xml

第三步:编写dao层并配置
UserDAOImpl extends HibernateDaoSupport implements IUserDAO



第四步:编写service层并配置,以及事务配置





















2.spring整合struts2原理及其配置
第一步:Action类的编写
第二步:struts.xml配置
第三步:jsp页面编写
第四步:web.xml上配置spring的上下文加载监听,struts的核心过滤器
需要注意的问题:
(1)spring管理action,是通过这个jar包:struts2-spring-plugin-2.3.24.jar
(2)把Action配置在applicationContext.xml上
需要注意两个问题:
第一:scope="prototype",因为Action是多例的,每请求一次就创建一次
第二:struts.xml上的class与id对应
(3)不管在不在applicationContext.xml上配置Action,都是由spring来管理Action对象
(4)Action对象需要注入service层对象,可以持有service层对象的引用,并提供set方法
private IUserService userService;
public void setUserService(IUserService userService) {
this.userService = userService;
}
===============================================================================================================================
回顾:
ssh整合xml配置方式:
1.spring整合hibernate
第一步:数据库相关:db.properties c3p0数据源连接池 id="c3p0DataSource"
第二步:spring管理了hibernate的sessionFactory对象

// 1.数据源连接池

// 2.hibernate.cfg.xml相关属性


hibernate.show_sql=true
方言...

        // 3.实体类映射文件
            
                
                    cn/itcast/domain/User.hbm.xml
                
            
    

2.spring声明式事务(xml配置实现,注解实现)
    //1.平台事务管理器
    
        
    
    
    //2.事务通知,本质是一种环绕通知
    
        
            
            
            
             //这里的方法名字与下面的切入点的方法名要对应
        
    
    
    //3.切面
    
        
        
    
    
    注解配置声明式事务,只需要把这里的通知和切面去掉,换成如下:
    
    service层的类上面加上@Transactional

    为什么要有事务?
    因为dao层针对数据库做操作,只能是一个一个做。增/删/改/查
    实际开发经常要做一组操作,一组操作,就叫做事务,这样的事务都是加在业务层,
    就算不是一组操作,有时候也需要回滚,也需要事务。

3.spring整合struts2
    有一个包非常重要:struts2-spring-plugin...jar
    web.xml配置struts2的核心过滤器,spring的上下文加载监听
    创建Action类
    struts.xml
    页面addUser.jsp
    注意:Action类持有service层的引用,提供set方法
        private IUserService userService;
        public void setUserService() {
        }
        Action类不需要配置在applicationContext.xml上

-----------------------------ssh框架整合过程(注解方式 重点掌握)-----------------------------
注解方式实现ssh整合
第一步:建web项目,导jar包
在xml方式的基础上,多加一个包:struts2-convention-plugin-2.3.24.jar
hibernate.cfg.xml不需要了,struts.xml可要可不要
第二步:web.xml配置spring的上下文监听,struts的核心过滤器
第三步:配置applicationContext.xml(web.xml需要加载applicationContext.xml)
整合hibernate
1.数据库相关 db.properties c3p0数据源
2.sessionFactory交给spring管理,配置LocalSessionFactoryBean
(1)关联dataSource
(2)hibernate属性 hibernate.show_sql=true
(3)加载实体类 PO 与数据库表对应

声明式事务
    1.事务管理器
    
        
    
    2.开启注解驱动
    

// 开启注解扫描  @Controller @Service @Repository @Component 

第四步:包结构,写代码
cn.itcast.dao 面向接口编程,有接口,有实现类
cn.itcast.service 面向接口编程,有接口,有实现类
cn.itcast.action
cn.itcast.domain 实体类上使用JPA注解,实体类映射文件也不需要
cn.itcast.utils

@Repository("userDao")
public class UserDAOImpl extends HibernateDaoSupport implements IUserDAO {

    // 注入sessionFactory
    @Autowired
    @Qualifier("sessionFactory")
    public void setSuperSessionFactory(SessionFactory factory) {
        super.setSessionFactory(factory);
    }

}

@Service
@Transactional
class UserServiceImpl implements IUserServcie {
    @Autowired
    private IUserDao userDao;
}

@Controller
@Scope("prototype")
@Namespace("/")
@ParentPackage("struts-default") json-default
public class UserAction {

    @Autowired
    private IUserService userService;
    
    
        
    

配置jsp页面

ssh学习需要把握
1.思路理清楚
2.每一步需要哪几个东西需要知道
3.互相的依赖关系

你可能感兴趣的:(Spring4学习笔记)