美文网首页
探索SSM(二)-Spring

探索SSM(二)-Spring

作者: Zephyr_07 | 来源:发表于2019-02-13 16:32 被阅读0次

    Spring

    注意~~

    ①必须在所有使用了dao的地方,包括调用它的servcie都要进行@Autowired注入,否则之后的注入就会失败..
    ②注解静态实例对象
    在Springframework里,我们是不能@Autowired一个静态变量。类加载后静态成员是在内存的共享区,因为当类加载器加载静态变量时,Spring上下文尚未加载。所以类加载器不会在bean中正确注入静态类,并且会失败。
    解决方法
    方式一:初始化到非静态对象再赋值

    @Component
    public class TestClass {
    
       private static AutowiredTypeComponent component;
    
       @Autowired
       private AutowiredTypeComponent autowiredComponent;
    
       @PostConstruct
       private void beforeInit() {
          component = this.autowiredComponent;
       }
    
       // 调用静态组件的方法
       public static void testMethod() {
          component.callTestMethod();
       }
    
    }
    

    方式二:直接用Spring框架工具类获取bean,定义成局部变量使用。

    public class TestClass {
    
        // 调用静态组件的方法
       public static void testMethod() {
          AutowiredTypeComponent component = SpringApplicationContextUtil.getBean("component");
          component.callTestMethod();
       }
    
    }
    

    Spring优势
    方便解耦,简化开发
    Spring就是一个大工厂,可以将所有对象创建和依赖关系维护交给 Spring 管理
    AOP 编程的支持
    Spring 提供面向切编程,可以方便的实现对序进行权限拦截、运监控等功能 提供面向切编程
    声明式事务的支持
    只需要通过配置就可以完成对事务的管理,而无手动编程

    web.xml

    <!--  每次请求都会创建一个工厂类 次请求都会创建一个工厂类 ,服务器端的资源就浪费了 ,一般情况下一个工程只有Spring 的工厂 类就OK 了. * 将工厂在服务器启动的时候创建好 ,将这个工厂放入到 ServletContext 域中 .每次获取工厂从 ServletContext 域中进行获取  -->
    配置监听器 : 
    <listener >
        <listener -class >org.springframework.web.context.ContextLoaderListener </ listener-class >
    </ listener >
    <context -param >
        <param-name >contextConfigLocation </param-name >
        <param-value >classpath:applicationContext.xml </param-value >
    </context-param >
    

    getBean操作

    WebApplicationContext applicationContext = WebApplicationContextUtils. getWebApplicationContext (ServletActionContext. getServletContext()); 
    CustomerService customerService = (CustomerService) applicationContext .getBean( "customerService" ); 
    

    3.5.5. applicationContext-service.xml

    配置注解扫描

    <! -- Spring 的注解开发 :组件扫描 (类上注解 : 可以直接使用属性注入的解 可以直接使用属性注入的解 ) -- >
    <context:component -scan base -package="com.itheima.spring.demo1"/>
    

    引入外部属性文件

    <context:property -placeholder location="classpath:jdbc.properties"/>
    

    在相关的类上添加注解 :

    @Component (value= "userDao ") public class UserDaoImpl implements UserDao { 
    
        @Override public void sayHello() { 
            System. out .println( "Hello Spring Annotation ..." );
            } 
        }
    

    注解解释
    1.2.2.1 Spring 中提供 @Component 的三个衍生注解 :( **功能目前来讲是一致的 **)
    @Controller :WEB 层 *
    @Service :业务层 业务层 *
    @Repository :持久层 持久层
    这三个注解是为了让标类本身的用途清晰

    1.2.2.2 注解的属性
    @Value :用于注入普通类型 .
    @Autowired :自动装配 :
    * 默认按类型进行装配
    * 按名称注入 按名称注入 :
    * @Qualifier: 强制使用名称注入 .
    @Resource 相当于 相当于 : * @Autowired 和@Qualifier 一起使用 .

    1.2.2.3 Bean 的作用范围注解 :
    @Scope:
    * singleton: 单例
    * prototype: 多例

    1.2.2.4 Bean的生命周期配置:
    @PostConstruct :相当于 init-method
    @PreDestroy :相当于 destroy-method

    AOP(applicationContext-trans.xml)

    底层代理机制 :
    Spring 的 AOP 的底层用到两种代理机制:
    * JDK 的动态代理 :针对实现了接口的类产生代理 .
    * Cglib 的动态代理 :针对没有实现接口的类产生代理 应用的是底层字节码增强技术, 生成当前类的子类对象 .

    注解解释
    Joinpoint(连接点): 所谓连接点是指那些被拦截到的点。在spring中,这些点指的是方法,因为spring只支持方法类型的连接点. Pointcut(切入点): 所谓切入点是指我们要对哪些Joinpoint进行拦截的定义.
    Advice(通知/增强): 所谓通知是指拦截到Joinpoint之后所要做的事情就是通知.通知分为前置通知,后置通知,异常通知,最终通知,环绕通知(切面要完成的功能)
    Introduction(引介): 引介是一种特殊的通知在不修改类代码的前提下, Introduction可以在运行期为类动态地添加一些方法或Field. Target(目标对象): 代理的目标对象
    Weaving(织入): 是指把增强应用到目标对象来创建新的代理对象的过程.
    spring采用动态代理织入,而AspectJ采用编译期织入和类装在期织入
    Proxy(代理): 一个类被AOP织入增强后,就产生一个结果代理类 Aspect(切面): 是切入点和通知(引介)的结合

    1.2.7.6 通知类型
    @Before 前置通知 :在目标方法执行之前执行
    @AfterReturing 后置通知 :在目标方法执行之后执行
    @Around 环绕通知 :在目标方法执行前和后执行
    @After 异常抛出通知:在目标方法执行出现异常的时候执行
    @AfterThrowing 最终通知 :无论目标方法是否出现异常最终通知都会执行

    AspectJ进行AOP开发 :XML的方式

    1.2.7.7 切入点表达式

    execution( 表达式 )
    表达式 : 
    [方法访问修饰符] 方法返回值 包名 .类名 .方法名 (方法的参数 ) 
    public * cn.itcast.spring.dao.*.*(..)
    * cn.itcast.spring.dao.*.*(..)
    * cn.itcast.spring.dao.UserDao+.*(..) *
    

    1.2.7.8 编写一个切面类

        public class MyAspectXml {
             // 前置增强
            public void before(){
                System. out .println( "前置增强 ===========" ); 
            } 
        }
    

    1.2.7.9 配置完成增强

    <! -- 配置切面类 -- >
    <bean id ="myAspectXml" class ="cn.itcast.spring.demo3.MyAspectXml" ></ bean >
    
    <! -- 进行 aop 的配置 -- >
    <aop:config >
        <! -- 配置切入点表达式 :哪些类的方法需要进行增强 哪些类的方法需要进行增强 -- >
        <aop:pointcut expression ="execution(* cn.itcast.spring.demo3.O rderDao.save(..))" id ="pointcut1" />
        <! -- 配置切面 -- >
        <aop:aspect ref ="myAspectXml" >
            <aop:before method ="before" pointcut -ref ="pointcut1" />
        </ aop:aspect >
    </ aop:config >
    
    AspectJ进行AOP开发 :注解的方式(常规)

    1.2.1.5 开启 aop 注解的自动代理 :
    <aop:aspectj -autoproxy/>

    1.2.1.8 配置切面 :
    <! -- 配置切面类 -- >
    <bean id ="myAspectAnno" "myAspectAnno" class ="cn.itcast.spring.demo4.MyAspectAnno" ></ bean >

    1.2.1.9 编写切面类

    @Aspect
    public class MyAspectAnno { 
    @Before ("MyAspectAnno.pointcut1()" )
        public void before(){
            System. out .println( "前置通知 ===========" ); 
        } 
    
    @AfterReturning ("MyAspectAnno.pointcut2()" ) 
        public void afterReturning(){
            System. out .println( "后置通知 ===========" ); 
        }
    
    @Around ("MyAspectAnno.pointcut3()" ) 
        public Object around(ProceedingJoinPoint joinPoint ) throws Throwable{
         System. out .println( "环绕前通知 ==========" );
         Object obj = joinPoint .proceed();
         System. out .println( "环绕后通知 ==========" );
         return obj ; 
         } 
    
    @AfterThrowing ("MyAspectAnno.pointcut4()" ) public void afterThrowing(){
        System. out .println( "异常抛出通知 ========" ); 
        }
    
    @After ("MyAspectAnno.pointcut4()" ) 
        public void after(){
        System. out .println( "最终通知 ==========" ); 
        } 
    
    @Pointcut ("execution(* cn.itcast.spring.demo4.ProductDao.save(..))" )
         private void pointcut1(){}
    @Pointcut ("execution(* cn.itcast.spring.demo4.ProductDa o.update(..))" )
        private void pointcut2(){}
    @Pointcut ("execution(* cn.itcast.spring.demo4.ProductDao.delete(..))" )
         private void pointcut3(){}
    @Pointcut ("execution(* cn.itcast.spring.demo4.ProductDao.find(..))" )
         private void pointcut4(){} }
    

    Spring事务管理

    连接池的配置
    ①内置连接池

    <-- 配置 Spring 的内置连接池 -- >
    <bean id ="dataSource" class ="org.springframework.jdbc.datasource.DriverManagerDataSource" >
        <property name ="driverClassName" value ="com.mysq l.jdbc.Driver" />
        <property name ="url" value ="jdbc:mysql:///spring_day02" />
        <property name ="username" value ="root" />
        <property name ="password" value ="123" />
    </ bean >
    

    ②DBCP连接池

    <-- 配置 DBCP 连接池 -- >
    <bean id ="dataSource" "dataSource" class ="org.apache.commons.dbcp.BasicDataSource" >
        <property name ="driverClassName" value ="com.mysql.jdbc.Driver" />
        <property name ="url" value ="jdbc:mysql:///spring_day02" />
        <property name ="username" value ="root" />
        <property name ="password" value ="123" />
    </ bean >
    

    ③c3p0连接池

    <! -- 配置 C3P0 连接池 -- >
    <bean id ="dataSource" "dataSource" class ="com.mchange.v2.c3p0.ComboPooledDataSource" >
        <property name ="driverClass" value ="com.mysql.jdbc.Driver" />
        <property name ="jdbcUrl" value ="jdbc:mysql:///spring_day02" />
        <property name ="user" value ="root" />
        <property name ="password" value ="123" />
    </ bean >
    

    事务的传播行为

    保证同一个事务中
    PROPAGATION_REQUIRED 支持当前事务,如果不存在 就新建一个(默认)
    PROPAGATION_SUPPORTS 支持当前事务,如果不存在,就不使用事务
    PROPAGATION_MANDATORY 支持当前事务,如果不存在,抛出异常 
    
    保证没有在同一个事务中
    PROPAGATION_REQUIRES_NEW 如果有事务存在,挂起当前事务,创建一个新的事务
    PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果有事务存在,挂起当前事务
    PROPAGATION_NEVER 以非事务方式运行,如果有事务存在,抛出异常
    PROPAGATION_NESTED 如果当前事务存在,则嵌套事务执行
    

    1.5.2 Spring的编程式事务-手动编写

    ggg.png

    1.5.3 Spring的声明式事务管理:XML 方式

    1.5.3.3 配置事务管理器

    <-- 事务管理器 -- >
    <bean id ="transactionManager" class ="org.sp ringframework.jdbc.datasource.DataSourceTransactionManager" >
        <property name ="dataSource" ref ="dataSource" />
    </ bean >
    

    1.5.3.4 配置事务的通知

    <! -- 配置事务的增强 -- >
    <tx:advice id ="txAdvice" "txAdvice" transaction -manager ="transactionManager" >
        <tx:attributes > <! -- isolation="DEFAULT" 隔离级别 propagation="REQUIRED" 传播行为 read -only="false" 只读 timeout=" -1" 过期时间 rollback -for="" -Exception no -rollback -for="" +Exception -- >
            <tx:method name ="transfer" propagation ="REQUIRED" />
        </ tx:attributes >
    </ tx:advice >
    

    1.5.3.5 配置 aop 事务
    <aop:config >
    <aop:pointcut expression ="execution(* cn.itcast.transaction.demo2.AccountServiceImpl.transfer(..))" id ="pointcut1" />
    <aop:advisor advice -ref ="txAdvice" pointcut -ref ="pointcut1" />
    </ aop:config >

    1.5.3 Spring的声明式事务管理:注解方式

    1.5.4.1 引入 jar包:


    hhh.jpg

    1.5.4.3 配置事务管理器 :

    <! -- 配置事务管理器 -- >
    <bean id ="transactionManager" class ="org.springframework.jdbc.datasource.DataSourceTransactionManager" >
        <property name ="dataSource" ref ="dataSource" />
    </bean >
    

    1.5.4.4 开启事务管理的注解 :

    <! -- 开启注解事务管理 -- >
    <tx:annotation -driven transaction -manager ="transactionManager" />
    

    1.5.4.5 在使用事务的类上添加一个注解: @Transactional


    ppp.jpg

    e.g. 本文仅供个人笔记使用,借鉴部分网上资料。

    相关文章

      网友评论

          本文标题:探索SSM(二)-Spring

          本文链接:https://www.haomeiwen.com/subject/ckwreqtx.html