美文网首页
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