美文网首页
SSM Spring

SSM Spring

作者: 极速魔法 | 来源:发表于2020-09-12 07:43 被阅读0次

    Spring

    分层的java se/ee 应用 全栈式 轻量级开源框架

    • 全栈式:对主流技术和框架进行整合,对三层架构提供了解决方案
    • 轻量级:使用了多少服务,启动加载的资源多少以及耦合度等

    Spring :IOC AOP 两大核心

    • IOC:控制反转, 对象的创建权 交给 spring
    • AOP :面向切面编程,不修改源码,对方法增强

    spring优势

    • 方便解耦,简化开发。
      • 耦合,指对象的依赖关系,一个模块更改其他模块也需要更改。
      • 解耦,降低程序间的依赖关系。配置文件+反射
    • AOP编程支持
    • 声明式事务的支持,通过配置
    • 方便测试
    • 方便集成各种框架

    IOC

    控制反转

    控制:java对象的控制权限(对象的创建,销毁)
    反转:对象的控制权限由开发者类中手动创建反转到spring容器控制

    // spring上下文对象,加载的同时创建了bean对象到容器中
    //aplicationContext.xml核心配置文件
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationCOntext.xml");
    context.getBean("userDao");
    

    Spring API

    BeanFactory 和ApplicationContext区别

    BeanFactory 第一次被调用 getBean()才会创建Bean对象
    ApplicationContext 类加载的同时,创建了bean对象到容器中

    BeanFactory实现类

    1. FileSystemXmlApplicationContext,磁盘路径,绝对路径
    2. ClassPathXmlApplicationContext ,类的根路径下加载
    3. AnnotationCOnfigApplicationContext

    getBean重载方法

    1. getBean(String id)
    2. getBean(Class<T> requireType)
    3. getBean(String id,Class<T> requireType)

    spring配置文件

    bean标签

    <bean id=“” class=“完全类名” scope=“” init-method=“初始化方法名” destroy-method=“销毁方法”>默认调用无惨构造

    scope取值:
    • singleton 默认,单例,生命周期与容器相同
    • prototype 多例,调用getBean()方法时才实例化
    Bean生命周期

    init-method 对象创建后执行 init-method

    实例化方式
    • 工厂静态方法
    // class staticFactory 调用factroy-method
     <bean id="userDao" class="com.lagou.factory.StaticFactory" factory-method="createUserDao" ></bean>
    
    • 工厂普通方法
      先生成工厂实例,再调用方法生成其他实例
    <bean id="dynamicBean" class="com.lagou.factory.DynamicFactoryBean" ></bean>
    <bean id="userDao" factory-bean="dynamicBean" factory-method="createUserDao" ></bean>
    

    DI 依赖注入

    对象注入

    构造方法

    <bean id="" class="">
        <!-- 0 第一个参数-- >
        <constructor-arg index="0" type="com.lagou.dao.IUserDao" ref="userDao"/>
    
        <!-- name代表构造方法中的参数名称-- >
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
    </bean>
    

    set方法

    <bean id="userService" class="com.lagou.userService">
        <!-- name属性的值 对应 setUserDao()方法名,ref用于引用类型,ref的值和引用类型id相同-->
        <property name="userDao" ref="userDao"></property>
    </bean>
    ref和id一致吗?
    

    P命名空间注入

    普通数据类型注入

    <bean id="userService" class="com.lagou.userService">
        <!-- value用于普通数据类型-->
        <property name="username" value="zhangfei"></property>
        <property name="age" value="18"></property>
    </bean>
    

    集合数据类型注入

    ...
    <property name="list">
        <list>
            <value>aaa</value>
            <ref bean="user"></ref>
        </list>
    </property>
    
    <!-- map-- >
    <property name="map">
        <map>
            <entry key="k1" value="ddd"></entry>
        </map>
    </property>
    
    <!-- properties-- >
    <property name="map">
        <props>
            <prop key="k1">value1</prop>
        </props>
    </property>
    

    配置文件模块化

    导入spring分文件
    <import resource=“application-service.xml”></import>

    加载jdbc.properties

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

    Spring注解

    注解扫描开启
    <contex:component-scan base-package="com.lagou"></context:component-scan>

    配置了 <bean>标签,生成类的实例对象到IOC容器
    @Component
    @Controller
    @Service
    @Repository

    <property>标签,依赖注入
    @AutoWired 根据引用类型完成依赖注入
    @Qualifier 结合@AutoWired使用,再根据名称查找
    @Resource(name=“”)
    @Value 普通类型

    bean的作用范围
    @Scope <bean scope=“”/>

    @Service("accountService") value值相当于 bean标签 id值
    

    @Configuration 配置类

    @Configuration
    @ComponentScan("com.lagou")
    @PropertySource(value="classpath:jdbc.properties") // value可以省略,只有一个值,且是value
    public class SpringConfig {
        
        @Value("${jdbc.driverClassName}")
        private String driver
        ...
    
        // key默认是方法名
        @Bean("dataSouce")
        public DataSouce getSouce(){
            ...
        }
    
        @Bean
        public QueryRunner getQueryRunner(@Autowired DataSource datasouce) {
            ...
        }
    }
    

    Spring注解Junit

    // 指定junit运行环境
    @RunWith(SpringJunit4ClassRunner.class)
    // 指定配置类或配置文件
    @ContextConfiguration(classes={SPringConfig.class})
    @ContextConfiguration({"classpath:applicationContext.xml"})
    

    AOP

    • 获取数据库连接,和线程绑定
    // ThreadLocal 线程存储类,key 是当前线程
     ThreadLocal<Connection> threadLocal = new ThreadLocal<>();
        // 获取存储的值
        threadLocal.get()
        // 设置存储的值
        threadLocal.set(conn)
        // 删除存储的值
        threadLocal.remove()
    
    • 释放资源
     /*手动事务改成自动提交事务
         连接归还到连接池
        解除线程绑定
    */
    conn.setAutoCommit(true);
    conn.close()
    
    // 调用threadlocal remov()方法
    connutils.remove();
    

    动态代理

    JDK代理 基于接口
    CGLIB 代理基于父类

    /* JDK动态代理
     * ClassLoader loader,类加载器,获取代理对象的类加载器
     * Class<?>[] interfaces ,被代理对象所需要实现的全部接口
     * InvocationHandler h,代理对象调用任意方法,都会执行    
    * InvocationHandler的invoke 方法
    */
    Proxy.newProxyInstance(ClassLoader loader,Class<?>[] interfaces,InvocationHandler h)
    
    /*
    * proxy ,当前代理对象引用
    * method, 被调用方法的引用
    * args,被调用目标方法的参数
    */
    Object invoke(Object proxy,Method method,Object[] args)
    
    method.invoke(accountService,args);
    
    /* cglib 代理
    * 参数1,目标类字节码对象
    * 参数2,动作类,代理对象调用目标对象的方法,会执行inetrcept方法
    */
    
    Enhancer.create(accountService.getClass(),new MethodIntercepstor(){
    /* o代表生成的代理对象,method:目标方法的引用,objects:目标方法参数, methodProxy 代理方法 
    */
        @Override
        public Object intercept(Object o,Method method,Object[]             objects,MethodProxy methodProxy) throws Throwable
            // methodProxy.invokeSuper(o,objects),调用代理方法的父类方法
            method.invoke(accountService, objects);
    })
    

    AOP优点

    • 运行期间,不修改源码,功能增强
    • 逻辑清晰
    • 减少重复复代码

    AOP对动态代理进行了封装,配置的方式对目标进行增强

    AOP术语

    • Target 被代理类
    • Proxy 生成的代理对象
    • Joinpoint (连接点) :可以被拦截增强的方法
    • Pointcut(切入点):真正被拦截增强的方法
    • Advice(通知/增强):增强的业务逻辑,
      • 前置通知
      • 后置通知
      • 异常通知
      • 最终通知
      • 环绕通知,spring提供的通过代码的方式来手动控制 通知的类型
    • Aspect(切面),切入点和通知的结合
    • Weaving(织入) ,增强 应用到目标对象的过程,创建新的代理对象
    
    <aop:config>
        <aop:pointcut id="myPoint" expression="execution(public void com.lagou.service.impl.AccountServiceImpl.*(..)"></aop:pointcut>
        <aop:aspect ref="myAdvice">
        <!--execution([修饰符] 返回类型 包名.类名.方法名(参数)) -->
        <!-- 目标类的transfer方法,使用myAdvice before方法前置增强 -->
            <aop:before method="before" pointcut="execution(public void com.lagou.service.impl.AccountServiceImpl.transfer())"></aop:before>
            <aop:after-returning point-ref="myPoint"></aop:after-returning>
        </aop:aspect>
    </aop:config>
    

    xml配置AOP

    execution([修饰符] 返回类型 包名.类名.方法名(参数))
    1.访问修饰符可以省略
    2. 返回值类型,包名,类名,方法名可以用 *匹配
        execution(* *.*.*.*())
    
    3.包名和类名中间一个点 . 代表当前包下的类,两个点.. 代表当前包及其子包的类
    execution(* *..*.*())
     
    4. 参数列表 .. 表示任意个数,任意类型的参数
    execution(* *..*.*(..))
    

    环绕通知

    <aop:around method=“around” point-ref=”myPoint”/>

    public Object around(ProceedingJoinPoint pjp) {
        Object processed = null;
        try {
            System.out.println("前置");
            //切点方法执行
            processed = pjb.processed();
    
            System.out.println("后置");
        } catch(Exception e) {
            System.out.println("异常");
        } finall {
            System.out.println("最终");
        }
    }
    

    AOP注解

    @Component
    @Aspect  // 升级为切面类
    public class MyAdvice {
        // 配置切入点和通知
        @Before("execution(* com.lagou.service.impl.AccountServiceImpl.*(..))")
        public void before() {
            ...
        }
    }
    

    /applicationContext.xml/

    <!--组件扫描-->
    <context:component-scan base-package="com.lagou"/>
    
    <!--aop的自动代理--> 
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    

    <bean id="accountService" class="com.lagou.service.impl.AccountServiceImpl"></bean>aop中配置的作用是代理类通过反射获取被代理对象的Class ,接口,方法等

    Spring JDBCTemplate

    JDBCTemplate jdbc= new JDBCTemplate(DataSource dataSource);
    
    int update(sql,params); //执行增、删、改语句
    
    List<T> query(sql,new BeanPropertyRowMapper<>(User.class)); //查询多个 
    T queryForObject(sql,new BeanPropertyRowMapper<>(User.class),params); //查询一个 
    new BeanPropertyRowMapper<>(); //实现ORM映射封装
    

    事务

    • 编程式事务

      • PlatformTransactionManager接口 spring事务管理器
    • 声明式事务

    事务的传播

    定义:一个业务方法被另一个方法调用,如何进行事务控制
    REQUIRED
    如果没有事务,就新建事务;如果已经存在事务,加入到事务中。被调用的方法必须进行事务控制

    SUPPORTS
    当前没有事务,以非事务进行。有事务,加入事务。当前被调用的方法有没有事务都可以执行(查询操作)

    事务管理器通过读取事务定义参数进行事务管理,然后会产生一系列的事务状态

    <!--通知-->
    <tx:advice id="txAdvice" transaction-manager="transactionmanger">
        <tx:attributes>
            <!-- name切点方法名称 com.lagou.service..*.*(..)中的方法,联系aop:advisor起来看-->
            <tx:method name="*"/>
        </tx:attributes>
    </tx:advic>
    
    <!--aop配置--> 
    <aop:config>
    
     <!--切面配置-->
      <aop:advisor advice-ref="txAdvice" pointcut="execution(*   com.lagou.serivce..*.*(..))">
      </aop:advisor> 
    </aop:config>
    

    平台事务管理器
    事务通知配置
    事务注解驱动配置(xml 或注解)

    Spirng ApplicationContext

    ServletContextListener 监听器监听web应用启动,加载Spring配置文件,创建ApplicationContext,存储到servletContext域中

     ApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
    
    Account account = (Account) webApplicationContext.getBean("account");
    
    

    相关文章

      网友评论

          本文标题:SSM Spring

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