spring框架基础

下载地址

在这里插入图片描述
Spring中文文档

需要的架包
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.2.0.RELEASE</version>
</dependency>
优点
  • Spring是一个开源的免费的框架(容器)
  • Spring是一个轻量级,非入侵式的框架
  • 控制反转(ioc),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持
  • Spring是一个开发JavaEE应用程序的轻量级的一站式框架。

Spring框架的组成

在这里插入图片描述
核心容器:核心容器提供 Spring 框架的基本功能。核心容器的主要组件是 BeanFactory,它是工厂模式的实现。BeanFactory 使用控制反转 (IOC) 模式将应用程序的配置和依赖性规范与实际的应用程序代码分开。
Spring 上下文:Spring 上下文是一个配置文件,向 Spring 框架提供上下文信息。Spring 上下文包括企业服务,例如 JNDI、EJB、电子邮件、国际化、校验和调度功能。
Spring AOP:通过配置管理特性,Spring AOP 模块直接将面向方面的编程功能集成到了 Spring 框架中。所以,可以很容易地使 Spring 框架管理的任何对象支持 AOP。Spring AOP 模块为基于 Spring 的应用程序中的对象提供了事务管理服务。通过使用 Spring AOP,不用依赖 EJB 组件,就可以将声明性事务管理集成到应用程序中。
Spring DAO:JDBC DAO 抽象层提供了有意义的异常层次结构,可用该结构来管理异常处理和不同数据库供应商抛出的错误消息。异常层次结构简化了错误处理,并且极大地降低了需要编写的异常代码数量(例如打开和关闭连接)。Spring DAO 的面向 JDBC 的异常遵从通用的 DAO 异常层次结构。
Spring ORM:Spring 框架插入了若干个 ORM 框架,从而提供了 ORM 的对象关系工具,其中包括 JDO、Hibernate 和 iBatis SQL Map。所有这些都遵从 Spring 的通用事务和 DAO 异常层次结构。
Spring Web 模块:Web 上下文模块建立在应用程序上下文模块之上,为基于 Web 的应用程序提供了上下文。所以,Spring 框架支持与 Jakarta Struts 的集成。Web 模块还简化了处理多部分请求以及将请求参数绑定到域对象的工作。
Spring MVC 框架:MVC 框架是一个全功能的构建 Web 应用程序的 MVC 实现。通过策略接口,MVC 框架变成为高度可配置的,MVC 容纳了大量视图技术,其中包括 JSP、Velocity、Tiles、iText 和 POI。

Spring配置

在这里插入图片描述
在这里插入图片描述

IOC和DI(在配置文件加载的时候,容器中管理的对象就已经初始化了)

  • IOC:控制反转,对象由容器创建, 传统的java对象的创建方式,是以new的方式在程序中硬编码创建的。所谓的“反转”指的是,对象的创建方式不是由程序员通过编码方式创建,而是通过spring容器创建。由容器创建对象。控制反转就是容器托管对象
  • DI:依赖注入,由容器对依赖关系进行初始化赋值

IOC创建对象方式

先创建实体类

public class Person {
	
	private String name;  //姓名
	private String speaking;  //说的话
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getSpeaking() {
		return speaking;
	}
	public void setSpeaking(String speaking) {
		this.speaking = speaking;
	}
	
	public void show() {
		System.out.println(this.name+" 说:" + this.speaking);
	}
}

打开applicationContext.xml,配置Person类

<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<!-- id唯一标识     Person person = new Person(); -->
	<bean id="person" class="com.gec.spring.bean.Person">
		<property name="name" value="李四"></property>
		<property name="speaking" value="hello world!"></property>
	</bean>

</beans>

测试

public static void main(String[] args) {
		//获取spring的对象容器    上下文 
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Person person = (Person) context.getBean("person");
		person.show();
	}

DI依赖注入方式

  • setter注入:需要有setter方法
    ref:引用Spring容器中创建好的对象 value:基本数据类型

第一种:setter注入

	<bean id="display" class="com.gec.spring.bean.Display"></bean>
    <bean id="host" class="com.gec.spring.bean.Host"></bean>
  
    <bean id="computer" class="com.gec.spring.bean.Computer">
    	<property name="display" ref="display"></property>
    	<property name="host" ref="host"></property>
    </bean>

第二种:p命名空间注入:需要依赖第三方约束

 <bean id="computer" class="com.gec.spring.bean.Computer" p:display-ref="display" p:host-ref="host">
 </bean>
  • 构造器注入
	<bean id="computer" class="com.gec.spring.bean.Computer">
    	<constructor-arg index="0" ref="host"></constructor-arg>
    	<constructor-arg index="1" ref="display"></constructor-arg>
    </bean>
  • 特殊类型的注入(集合),常用于框架的配置
    创建实体类
public class Department {

	private String name;
	//定义员工列表数据
	private List<Employee> empList;
	private Set<Employee> empSet;
	private Map<String, Employee> empMap;
	private Properties pp;
	
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public List<Employee> getEmpList() {
		return empList;
	}
	public void setEmpList(List<Employee> empList) {
		this.empList = empList;
	}
	public Set<Employee> getEmpSet() {
		return empSet;
	}
	public void setEmpSet(Set<Employee> empSet) {
		this.empSet = empSet;
	}
	public Map<String, Employee> getEmpMap() {
		return empMap;
	}
	public void setEmpMap(Map<String, Employee> empMap) {
		this.empMap = empMap;
	}
	public Properties getPp() {
		return pp;
	}
	public void setPp(Properties pp) {
		this.pp = pp;
	} 
}

使用 list、set、map、props注入集合关系:

<bean id="department" class="com.gec.spring.bean.Department">
		<property name="name" value="财务部"></property>
		
		<property name="empList">
			<list>
				<!--如果是基本类型,用value-->
				<ref bean="emp1"/>
				<ref bean="emp2"/>
			</list>
		</property>
		
		<property name="empSet">
			<set>
				<ref bean="emp1"/>
				<ref bean="emp2"/>		
			</set>
		</property>
		
		<property name="empMap">
			<map>
				<entry key="1" value-ref="emp1"></entry>
				<entry key="2" value-ref="emp2"></entry>
			</map>
		</property>
		
		<property name="pp">
			<props>
				<prop key="pp1">hello</prop>
				<prop key="pp2">world</prop>
			</props>
		</property>
	</bean>
   <bean id="emp1" class="com.gec.spring.bean.Employee">
		<property name="id" value="1"></property>
		<property name="name" value="张三"></property>
	</bean>
	<bean id="emp2" class="com.gec.spring.bean.Employee">
		<property name="id" value="2"></property>
		<property name="name" value="李四"></property>
	</bean>
  • 接口注入

  • 注解注入

     1.导入约束:context约束
     2.配置注解的支持:<context:annotation-config></context:annotation-config>
    
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 开启注解配置   -->
    <context:annotation-config></context:annotation-config>

@Autowired
直接在属性上使用即可,也可以字set方法上使用
使用Autowired我们可以不用再写set方法,前提是自动装配的属性在IOC容器中存在

public class User {

    private String name;
    @Autowired
    private Dog dog;
    @Autowired
    private Cat cat;

    public User() {
        System.out.println("454545");
    }

@Component,@Value

<!--  指定要扫描的包,这个包下的注解就会生效  -->
    <context:component-scan base-package="com.kuang.pojo"></context:component-scan>
    <!-- 开启注解配置   -->
    <context:annotation-config></context:annotation-config>
//相当于<bean id="user" class="com.kuang.pojo.User"></bean>
@Component
public class User {

    @Value("张三")
    public String name;
}

在这里插入图片描述

Bean的作用域

在这里插入图片描述
在这里插入图片描述

Sping的自动装配

在这里插入图片描述

byName

<bean id="computer" class="com.gec.spring.bean.Computer" autowire="byName"></bean>

byType

 <bean id="computer" class="com.gec.spring.bean.Computer" autowire="byType"></bean>

使用Java的方式配置Spring

实体类

@Component
public class User {

    @Value("张三")
    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                '}';
    }
}

配置类

//代表这是一个配置类,和之前的beans.xml是一样的
//也会被spring容器托管,因为它本身就是一个@Component
@Configuration
@ComponentScan("com.kuang.pojo")//扫描包
//还可以通过import注解引入其他配置类
public class KuangConfig {

    //注册Bean,相当于xml文件里的bean标签
    //方法名相当于bean标签的id属性,返回值相当于class属性
    @Bean
    public User getUser(){
        return new User();
    }
}

测试

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(KuangConfig.class);
        User getUser = (User) context.getBean("getUser");

        System.out.println(getUser.getName());

    }
}

Spring的AOP编程

介绍

在不影响业务本来的情况下,实现动态增加功能,大量应用再日志,事务。。等等
(1)AOP Aspect Oriented Programming 面向切面编程,其实就是拦截器
(2)JavaEE应用中,常见的“拦截”的技术:
原生平台中的Filter, 过滤器。过滤的是一切可访问的资源,包括,页面,图片,样式,servle/jsp。
Spring中的AOP, 主要是拦截业务层的方法。对业务方法的功能增强。
MVC框架,也提供了拦截器。拦截的是控制器,主要是action(Struts2), handler(springmvc).
(3) 拦截的概念:对目标对象的代理,并进行功能的增强。简单来说,就是增强功能。
对于“共性”的问题,如果OOP解决不了的,可以使用AOP来解决“通用性”的问题。AOP是对OOP的补充的作用。也就是解决通用性问题。作用:降低耦合度。
(4)aop编程的术语

  • aspect 切面 对共性问题的抽象 , 拦截器类
  • pointcut 切入点 被拦截的方法
  • advice 通知,功能增强, 增强的方式:前置增强,后置增强,环绕增强,异常增强,最终增强。

导包

<dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.4</version>
    </dependency>

AOP编程的实现方式

  • 实现接口的方式(spring低版本)
  • schema的方式(使用XML配置)
    MyAspect类,拦截器类
/**
 * 拦截器类
 * @author gec
 *
 */
public class MyAspect {

	//1. 前置增强(XML配置)
	public void before(JoinPoint joinPoint) {
		Object[] args = joinPoint.getArgs();  //获取被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName();   //被拦截方法的名称
		Object target = joinPoint.getTarget();  //拦截的目标实例(业务类的实例)
		//进一步完成功能 的增强
		System.out.println("前置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target);
	}
	
	//2. 后置增强(XML配置)
	public void afterReturning(JoinPoint joinPoint,Object returnValue) {
		Object[] args = joinPoint.getArgs();  //获取被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName();   //被拦截方法的名称
		Object target = joinPoint.getTarget();  //拦截的目标实例(业务类的实例)
		//进一步完成功能 的增强
		System.out.println("后置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target+",业务方法的返回值 :"+returnValue);
	}
	
	//3. 环绕增强
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		Object[] args = pjp.getArgs();  //获取被拦截方法的参数列表
		String methodName = pjp.getSignature().getName();   //被拦截方法的名称
		Object target = pjp.getTarget();  //拦截的目标实例(业务类的实例)
		System.out.println("环绕-前置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target);
		
		Object returnValue = pjp.proceed();  //调用核心业务方法
		
		System.out.println("环绕-后置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target+",业务方法的返回值 :"+returnValue);
		
		return returnValue;
	}
}

拦截器的配置 ,要先添加aop的命名空间

<beans
	xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans 
	http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
	http://www.springframework.org/schema/aop 
	http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
	
	<!-- 容器托管业务类,拦截器类 -->
	<bean id="userService" class="com.gec.spring.service.impl.UserServiceImpl"></bean>
	<bean id="myAspect" class="com.gec.spring.aop.MyAspect"></bean>
	
	<!-- aop的织入 -->
	<aop:config>
		<aop:pointcut id="pointcut" expression="execution(public * com.gec.spring.service.impl.*.*(..))" />
		<aop:aspect ref="myAspect">
			<aop:before method="before" pointcut-ref="pointcut"/>
			<aop:after-returning method="afterReturning" returning="returnValue" pointcut-ref="pointcut"/>
			<aop:around method="around" pointcut-ref="pointcut"/>
		</aop:aspect>
	</aop:config>
	
</beans>

测试 业务类返回的是代理业务接口,不能使用实现类接收

public class TestAspect {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("aop.xml");
		
		//返回的是代理业务接口(被增强后),不能用实现类接收
		UserService userService = (UserService) context.getBean("userService");
		String msg = userService.findUserById("001");
		System.out.println(msg);
	}
}

结果
在这里插入图片描述

  • 注解的方式
    在切面类中添加注解配置
/**
 * 拦截器类
 * @author gec
 *
 */
@Aspect
public class MyInterceptor {

	//1. 前置增强(XML配置)
	@Before("execution(public * com.gec.spring.service.impl.*.*(..))")
	public void before(JoinPoint joinPoint) {
		Object[] args = joinPoint.getArgs();  //获取被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName();   //被拦截方法的名称
		Object target = joinPoint.getTarget();  //拦截的目标实例(业务类的实例)
		//进一步完成功能 的增强
		System.out.println("前置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target);
	}
	
	//2. 后置增强(XML配置)
	@AfterReturning(pointcut="execution(public * com.gec.spring.service.impl.*.*(..))",returning="returnValue")
	public void afterReturning(JoinPoint joinPoint,Object returnValue) {
		Object[] args = joinPoint.getArgs();  //获取被拦截方法的参数列表
		String methodName = joinPoint.getSignature().getName();   //被拦截方法的名称
		Object target = joinPoint.getTarget();  //拦截的目标实例(业务类的实例)
		//进一步完成功能 的增强
		System.out.println("后置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target+",业务方法的返回值 :"+returnValue);
	}
	
	//3. 环绕增强
	@Around("execution(public * com.gec.spring.service.impl.*.*(..))")
	public Object around(ProceedingJoinPoint pjp) throws Throwable {
		Object[] args = pjp.getArgs();  //获取被拦截方法的参数列表
		String methodName = pjp.getSignature().getName();   //被拦截方法的名称
		Object target = pjp.getTarget();  //拦截的目标实例(业务类的实例)
		System.out.println("环绕-前置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target);
		
		Object returnValue = pjp.proceed();  //调用核心业务方法
		
		System.out.println("环绕-后置方法名:"+methodName+",参数列表:"+Arrays.toString(args)+",目标对象实例:"+target+",业务方法的返回值 :"+returnValue);
		
		return returnValue;		
	}
	
}

在配置文件启动注解配置

<bean id="myInterceptor" class="com.gec.spring.aop.MyInterceptor"></bean>
	<!-- 启动aop的注解配置 -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

spring中的事务管理

  • 声明式事务:AOP
<!-- 配置声明式事务,官网的固定格式 -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="datasource"/>
    </bean>

    <!-- 结合AOP实现事务的织入 -->
    <!-- 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
    <!--  给哪些方法配置事务  -->
    <!--  配置事务的传播特性:new propagation  -->
        <tx:attributes>
            <tx:method name="addUser" propagation="REQUIRED"/>
            <tx:method name="*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    
    <!-- 配置事务切入,在哪里使用事务 -->
    <aop:config>
        <aop:pointcut id="txPointCut" expression="execution(* com.kuang.mapper.*.*(..))"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
    </aop:config>
  • 编程式事务:需要在代码中进行事务管理

为什么要配置事务?
如果不配置事务,可能会存在数据提交不一致的情况

笔记

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值