Spring框架
spring模块
一站式的轻量级框架。
1. 非侵入式编程:
不需要继续类,不需要实现接口
2. 支持JavaEE三层开发
数据库:支持mybaits,hibernate,封装jdbc
业务逻辑层:ioc,aop
表现层:对页面框架有支持,springmvc,struct2
spring核心功能
1. IoC:控制反转:将new对象的权利交给了xml
DI:依赖注入(控制反转的实现手段)
2. AOP:面向切面编程
在不改变以前代码的流程下,加入一段代码
spring的优点
1).使用Spring的IOC容器,将对象之间的依赖关系交给Spring,降低组件之间的耦合性,让我们更专注于应用逻辑
2)可以提供众多服务,事务管理,WS等。
3)AOP的很好支持,方便面向切面编程。
4)对主流的框架提供了很好的集成支持,如Hibernate,Struts2,JPA等
5)Spring DI机制降低了业务对象替换的复杂性。
6)Spring属于低侵入,代码污染极低。
7)Spring的高度可开放性,并不强制依赖于Spring,开发者可以自由选择Spring部分或全部S
spring的xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
SpringIoC
控制反转指的就是将对象的创建权反转给(交给)了Spring
1.导入springIOC所需要的jar包
<!-- spring开发依赖的jar star-->
<!-- spring-core -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- spring-beans -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- spring-expression -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-expression</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- commons-logging -->
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.2</version>
</dependency>
<!-- log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
<!-- spring开发依赖的jar end-->
<!-- spring-aop start -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- spring-aop end -->
具体实现IOC(实现方式:依赖注入)
创建一个实体类 实现get和set方法
public class User implements Serializable {
private String name;
public User() {
}
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
创建接口
对spring的配置文件配置bean的信息
<bean id="user" class="com.spring.demo.Person">
<property name="name" value="zje"></property>
</bean>
property 标签给name赋值 value =’‘值’’
测试代码
public class TextIoc {
@Test
public void textUser()
{
//1.获取spring配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("Bean.xml");
//2.由配置文件返回对象u
User p = (User )context.getBean("user ");
System.out.println(p.getName());
}
}
输出的结果为"zje"
多种方式实现依赖注入
- 构造注入
使用构造函数注入:添加构造函数
public class UserDaoImpl implements UserDao{
....
}
public class UserServiceImpl implements UserService{
private UserDao dao;
public UserServiceImpl(UserDao dao){
this.dao = dao
}
}
在xml文件中配置
<bean id="userDao" class="com.spring.dao.impl.UserDaoImpl">
</bean>
<bean id="userService" class="com.spring.service.impl.userServiceImpl">
<constructor-arg>
<ref bean ="userDao"/>
</constructor-arg>
</bean>
- p命名空间注入
语法:p:属性="属性值"
<bean id="user" class="com.spring.demo.Person" p:name="zhang" p:age="">
</bean>
<bean id="userService" class="com.spring.service.impl.userServiceImpl" p:dao-ref="userDao">
3.注入特殊符号
使用<![CDATA[]]>
<bean id="user" class="com.spring.demo.Person">
<property name="name" >
<value><![CDATA[李<陈]]></value>
</property>
</bean>
SpringAop
面向切面编程是软件编程思想发展到一定阶段的产物,是对面向对象编程的有益补充,AOP能够使用一种更好的方式来解决OOP不能很好解决的横切关注点问题以及相关的设计难题来实现松散耦合。面向切面编程简单的来说就是在不改变原来程序的基础上增加新的功能。
切面编程的基本概念
- 切面(Aspect)一个模块化的横切逻辑,可能会横切多对象
- 连接点(Join Point):程序执行中的某个具体的执行点。
- 增强处理(Advice):切面在某个特定的连接点上执行的代码逻辑。
- 切入点:(Pointcut):对连接点的特征进行描述,可以使用正则表达式。
- 织入(Weaving) :将增强处理链接到应用程序中的类型或对象上的过程。
实现springAop需要的jar包
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
<!-- https://mvnrepository.com/artifact/aopalliance/aopalliance -->
<dependency>
<groupId>aopalliance</groupId>
<artifactId>aopalliance</artifactId>
<version>1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
1、定义切面
public class beforeLogger {
private Logger log = Logger.getLogger(beforeLogger.class);
public void brfore(){
log.info("方法执行之前");
}
}
在配置文件中对相关组件进行声明
<bean id="beforeLogger" class="aop.beforeLogger"></bean>
2、定义切入点
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* service.UserServiceImpl.*(..))"/>
<aop:aspect ref="beforeLogger">
<!--织入-->
<aop:before method="brfore" pointcut-ref="pointcut" throwing="e"></aop:before>
</aop:aspect>
</aop:config>
在执行方法之前会执行 brfore()方法
其他增强类型
1.前置增强:在执行方法前调用
<aop:before method="before" pointcut-ref="pointcut"></aop:before>
2.后置增强:在执行方法(正常执行完成后)后调用
<aop:after-returning method="afterReturning"
pointcut-ref="pointcut" returning="result"></aop:after-returning>
3.异常抛出增强:执行方法异常时执行
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"></aop:after-throwing>
4.最终增强:无论方法时正常还是异常退出都会执行
<aop:after method="afterReturning"
pointcut-ref="pointcut" returning="result"></aop:after>
5.环绕增强
public class ArroundLogger {
private static final Logger log = Logger.getLogger(ArroundLogger.class);
public Object arroundLogger(ProceedingJoinPoint jp) throws Throwable {
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参" + Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed();
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值" + result);
return result;
} catch (Throwable e) {
log.error(jp.getSignature().getName() + "方法发生异常:" + e);
e.printStackTrace();
throw e;
} finally {
log.info(jp.getSignature().getName() + "方法结束执行");
}
}
}
<aop:around method="arroundLogger" pointcut-ref="pointcut"></aop:around>
Spring-mybatis的整合
Spring-mybatis整合所需要的jar包
- 数据库+mybatis
<!-- 数据库 start -->
<!-- mysql -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.16</version>
</dependency>
<!-- mybatis -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<!-- 数据库 end -->
- 数据源
<!-- 数据源 start-->
<!-- commons-dbcp2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-dbcp2</artifactId>
<version>2.6.0</version>
</dependency>
<!-- commons-pool2 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.6.0</version>
</dependency>
<!-- 数据源 end-->
- mybatis-spring 的支持
<!-- mybatis-spring整合 start-->
<!-- mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- spring-tx -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.8.RELEASE</version>
</dependency>
<!-- mybatis-spring整合 end-->
配置文件
- mybatis的配置文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${uname}"/>
<property name="password" value="${upwd}"/>
</dataSource>
</environment>
</environments>
</configuration>
- spring的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp2.BasicDataSource" destroy-method="close">
<!--
BasicDataSource提供了close()方法关闭数据源,所以必须设定destroy-method=”close”属性, 以便Spring容器关闭时,数据源能够正常关闭;销毁方法调用close(),是将连接关闭,并不是真正的把资源销毁
-->
<property name="driverClassName" value="com.mysql.cj.jdbc.Driver"></property>
<property name="url">
<!-- 千万注意,这里不能换行 -->
<value><![CDATA[jdbc:mysql://127.0.0.1:3306/stusys?serverTimezone=UTC&useUnicode=true&characterEncoding=UTF-8]]></value>
</property>
<property name="username" value="root"></property>
<property name="password" value="root"></property>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
<!--单个单个类的扫描 -->
<!--<bean id="classesMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<property name="mapperInterface" value="mapper.classes.ClassesMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>-->
<!-- 扫描整个包下的所有:命名规则就是首字母改成小写 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="mapper" />
</bean>
<bean id="classesService" class="service.impl.ClassesServiceImpl">
<property name="classesMapper" ref="classesMapper"></property>
</bean>
</beans>
mapper层
- 接口
package mapper.classes;
import pojo.Classes;
import java.util.List;
public interface ClassesMapper {
List<Classes> selectList();
}
- mapper的xml文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="mapper.classes.ClassesMapper">
<resultMap id="classesMap" type="pojo.Classes">
<id property="id" column="id"></id>
<result property="name" column="name"></result>
</resultMap>
<select id="selectList" resultMap="classesMap">
select id,name from classes
</select>
</mapper>
测试
@Test
public void testRole(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassesService classesService = (ClassesService)context.getBean("classesService");
}
spring的注解
一:使用注解实现IoC的配置
1. 使用注解定义bean
import org.springframework.stereotype.Component;
@Component
import org.springframework.stereotype.Repository;
@Repository:用于标注DAO类
import org.springframework.stereotype.Service;
@Service:用于标注业务类
import org.springframework.stereotype.Controller;
@Controller:用于标注控制器类
注意:@Component的作用等价于@Repository,@Service,@Controller。使用特定的注解使组件用途更加清晰,推荐使用特定的注解
2. 使用注解实现Bean组件的装配
1.spring注解完成装配
spring提供了@Autowired注解实现Bean的装配
若容器中有一个以上的类型相匹配的Bean时,则可以使用 @Qualifier()指定所需要的Bean名称
@Controller("orderDetailsServiceImpl")
public class OrderDetailsServiceImpl implements OrderDetailsService {
@Autowired
@Qualifier("orderDetailsBiz")
private OrderDetailsBiz orderDetailsBiz;
@Override
public List<OrderDetail> seleclistOrderDetails() {
return orderDetailsBiz.seleclistOrderDetails();
}
public OrderDetailsBiz getOrderDetailsBiz() {
return orderDetailsBiz;
}
public void setOrderDetailsBiz(OrderDetailsBiz orderDetailsBiz) {
this.orderDetailsBiz = orderDetailsBiz;
}
}
2.使用Java标准注解完成装配
@Resource(name = “”)
@Resource的name属性,默认情况下,Spring将这个属性的值解释为要注入的Bean的名称
@Controller("orderDetailsServiceImpl")
public class OrderDetailsServiceImpl implements OrderDetailsService {
@Resource(name = "orderDetailsBiz")
private OrderDetailsBiz orderDetailsBiz;
@Override
public List<OrderDetail> seleclistOrderDetails() {
return orderDetailsBiz.seleclistOrderDetails();
}
public OrderDetailsBiz getOrderDetailsBiz() {
return orderDetailsBiz;
}
public void setOrderDetailsBiz(OrderDetailsBiz orderDetailsBiz) {
this.orderDetailsBiz = orderDetailsBiz;
}
}
3. 加载注解定义的Bean
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="biz,service"></context:component-scan>
</beans>
首先在spring配置文件中添加对context命名空间的声明,然后使用context命名空间下的compoent-scan标签扫描注解标注的类,多个包名用逗号隔开。
二:使用注解定义切面
使用注解标注切面
import org.aspectj.lang.annotation.Aspect;
@Aspect
public class beforeLogger {
@Pointcut("execution(* action.UserAction.*(..))")
public void pointcut(){}
private Logger log = Logger.getLogger(beforeLogger.class);
@Before("execution(* action.UserAction.*(..))")
public void brfore(){
log.info("方法执行之前");
}
@After("execution(* action.UserAction.*(..))")
public void afterLogger(JoinPoint jp){
log.info(jp.getSignature().getName()+"方法结束执行");
}
@AfterThrowing(pointcut = "execution(* action.UserAction.*(..))",throwing = "e")
public void afterThrowing(JoinPoint jp,RuntimeException e){
log.error(jp.getSignature().getName()+"犯法发生异常:"+e);
}
@Around("execution(* action.UserAction.*(..))")
public Object arroundLogger(ProceedingJoinPoint jp) throws Throwable {
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法入参" + Arrays.toString(jp.getArgs()));
try {
Object result = jp.proceed();
log.info("调用" + jp.getTarget() + "的" + jp.getSignature().getName() + "方法。方法返回值" + result);
return result;
} catch (Throwable e) {
log.error(jp.getSignature().getName() + "方法发生异常:" + e);
e.printStackTrace();
throw e;
} finally {
log.info(jp.getSignature().getName() + "方法结束执行");
}
}
@AfterReturning(pointcut = "pointcut()",returning = "result")
public void afterReturning01(JoinPoint jp,Object result){
log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法。方法入参:"+result);
}
@AfterReturning(pointcut = "pointcut()",returning = "result")
public void afterReturning(JoinPoint jp,Object result){
log.info("调用"+jp.getTarget()+"的"+jp.getSignature().getName()+"方法。方法入参:"+result);
}
}
使用 @Aspect 注解将beforeLogger定义为切面,并且使用 @Before注解将brfore()方法定义为前置增强,使用 @AfterReturning 注解将afterReturning()方法定义为后置增强,使用 @AfterThrowing注解将afterThrowing()方法定义为异常增强,使用 @After注解将方法afterLogger()定义为最终增强,使用 @Around 注解将方法arroundLogger()定义为环绕增强。切入点表达式使用 @Pointcut注解来表示,而切入点签名则需要通过一个普通的方法定义来提供。
在配置文件中织入
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<context:component-scan base-package="biz,service"></context:component-scan>
<bean class="aop.beforeLogger "></bean>
<aop:aspectj-autoproxy/>
</beans>