基本介绍
Spring是什么?
Spring是Spring团队开发的一款框架
这个框架的主要功能就是
- 整合第三方框架
- 为业务逻辑层提供事务支持
- 还提供了WebMVC这个解决方案
- 还提供了 DAO层的解决方案
- JDBCTemplate
主要特性 DI(依赖注入)、IOC(控制反转)、AOP(面向切面编程)
七大模块
Core:核心模块 主要功能IOC、DI
AOP:面向切面编程
WebMVC:SpringMVC Controller层的解决方案(封装了servlet 简化请求与响应)
DAO:DAO层的解决方案 JDBCTemplate (类似于dbutils)
ORM:Object Relation Mapping 对象关系映射 用于整合第三方DAO层的框架(mybatis、hibernate)
Web:Spring对Web的支持
Context:上下文支持模块
代码编写
导包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.26</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
配置文件bean-base.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 生成User类的实例 -->
<bean id="user" class="com.qfedu.edu.pojo.User" />
</beans>
User类
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private Integer id;
private String username;
private String password;
}
测试
public class Test {
public static void main(String[] args) {
//第一步:获取到初始化的容器
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean-base.xml");
//第二步:就可以实现实例的获取
User user = (User) context.getBean("user");
System.out.println(user);
}
}
控制反转
理解:控制反转。
原来创建Java对象的时候是程序员自己创建;
学习完Spring之后,这个对象的创建可以交给Spring去管理、创建。
也就是说控制反转是指Spring控制了对象的创建,创建对象的权力反转了。
无参数对象
<!--
id 实例的唯一标识
class 生成实例信息的类路径
name 实例名称
scope="singleton" 单例 默认情况下是单例
scope="prototype" 生成类的实例是多例
init-method="" 对象放入IOC容器时 执行的方法
destroy-method="" 对象在IOC容器中销毁时 执行的方法
lazy-init="true" 懒加载 类被使用时生成对象放到IOC容器中
在容器启动的时候 不生成对象放到IOC中
IOC容器 就是一个ConcurrentHashMap集合
-->
<bean id="user" lazy-init="true" class="com.qfedu.edu.pojo.User"></bean>
带参数对象
<!-- 创建有参数构造器的生成对象 通过参数下标赋值 -->
<!--
<bean id="user" class="com.qfedu.edu.pojo.User">
<constructor-arg index="0" value="1"></constructor-arg>
<constructor-arg index="1" value="buliyat"></constructor-arg>
<constructor-arg index="2" value="123"></constructor-arg>
</bean>
-->
<bean id="user" class="com.qfedu.edu.pojo.User">
<constructor-arg name="id" value="1"></constructor-arg>
<constructor-arg name="username" value="buliyat"></constructor-arg>
<constructor-arg name="password" value="123"></constructor-arg>
</bean>
静态工厂
public class UserFactory {
public static User getStaticUser() {
return new User(1,"静态的用户名","静态的密码");
}
}
<bean id="user" class="com.qfedu.edu.factory.UserFactory" factory-method="getStaticUser"></bean>
非静态工厂
public class UserFactory {
public User getUserInstance() {
return new User(1,"非静态的用户名","非静态的密码");
}
}
<bean id="userFactory" class="com.qfedu.edu.factory.UserFactory"></bean>
<bean id="user" factory-bean="userFactory" factory-method="getUserInstance"></bean>
依赖注入
理解:依赖注入。A类引用了B类的方法,即A类依赖于B类。在开发时Controller调用Service,Service调用DAO或Mappe。我们认为:Controller依赖于Service,Service依赖于DAO。这就是依赖。注入的是IOC容器中的对象或者IOC容器中的具体值。
set注入
Service
public class UserService {
private UserDAO userDAO;
private String str;
public void setStr(String str) {this.str = str;}
public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}
public void print() {userDAO.print();}
}
DAO
public class UserDAO {
public void print(){
System.out.println("-----userDAO执行了------");
}
}
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="userDAO" class="com.qfedu.edu.di.UserDAO" />
<bean id="userService" class="com.qfedu.edu.di.UserService">
<property name="userDAO" ref="userDAO" />
<property name="str" value="xiaobobo" />
</bean>
</beans>
测试
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean-di.xml");
UserService userService = context.getBean(UserService.class);
userService.print();
}
}
p标签注入
前提:注入位置必须写set方法 即p标签注入 实际上是set注入
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="userDAO" class="com.qfedu.edu.di.UserDAO"></bean>
<bean id="userService" class="com.qfedu.edu.di.UserService" p:userDAO-ref="userDAO"></bean>
</beans>
内部bean注入
内部bean注入也必须给定我们的set方法
即内部bean注入 也是set注入内部bean注入时
只给成员变量赋值 并没有将对象放入IOC容器中 很少使用
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="userService" class="com.qfedu.edu.di.UserService">
<property name="userDAO">
<bean id="userDAO" class="com.qfedu.edu.di.UserDAO"></bean>
</property>
</bean>
</beans>
构造器注入
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<bean id="userDAO" class="com.qfedu.edu.di.UserDAO"></bean>
<bean id="userService" class="com.qfedu.edu.di.UserService">
<constructor-arg name="userDAO" ref="userDAO"></constructor-arg>
</bean>
</beans>
自动装配
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd"
default-autowire="byType">
<!--
autowire:"byName" :通过名字进行装配
autowire="byType":这个表示的是通过类型去实现自动装配
-->
<bean id="userDAO" class="com.qfedu.edu.di.UserDAO" />
<bean id="userService" class="com.qfedu.edu.di.UserService" />
</beans>
注解实现
Service
/**
将下面类的对象放到IOC容器中
@Component 一般用在其他的地方 下面两注解的父类
@Service 一般用在业务逻辑层
@Repository 一般用在DAO层
*/
@Component(value = "userService")// 设置该类在IOC中的名称 默认为类名的首写字母小写
@Scope(value = "singleton") // 设置 单例 或者 多例
@Lazy // 懒加载
public class UserService {
@Resource // 先名字 再类型
@Autowired // 先类型 再名字
private UserDAO userDAO;
@PostConstruct // 对象放到IOC容器之后 要执行的方法
public void init(){}
@PreDestroy // 对象在IOC容器中销毁时 要执行的方法
public void destory(){}
public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}
}
DAO
@Repository(value = "userDAO")
public class UserDAO {
public void print(){}
}
面向切面
手动实现AOP
Service
@Service
public class UserService {
public void update() {System.out.println("用户更新操作");}
public void add() {System.out.println("添加操作");}
}
TransactionAop
@Component
public class TransactionAop {
public void beginTransaction() {System.out.println("打开事务");}
public void commitTransaction() {System.out.println("提交事务");}
public void closeTransaction() {System.out.println("关闭事务");}
}
代理工厂
@Service
public class UserServiceProxyFactory implements MethodInterceptor {
@Resource
private UserService userService;
@Resource
private TransactionAop transactionAop;
public UserService getUserServiceProxy(){
Enhancer enhancer=new Enhancer();
enhancer.setCallback(this);
enhancer.setSuperclass(UserService.class);
return (UserService) enhancer.create();
}
public Object intercept(Object o, Method method,
Object[] objects, MethodProxy methodProxy) throws Throwable {
transactionAop.beginTransaction();
Object invoke = method.invoke(userService, objects);
transactionAop.commitTransaction();
transactionAop.closeTransaction();
return invoke;
}
}
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-4.0.xsd">
<!-- 设置注解扫描的包 -->
<context:component-scan base-package="com.qfedu.edu.aop.sx" />
</beans>
测试
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean-aop-sx.xml");
UserServiceProxyFactory bean = context.getBean(UserServiceProxyFactory.class);
UserService userServiceProxy = bean.getUserServiceProxy();
userServiceProxy.update();
}
}
配置实现AOP
Service AOP类
public class Aop {
public void before() {System.out.println("--------执行目标方法之前--------");}
public void after() {System.out.println("--------执行目标方法之后--------");}
public void afterThrowing(){System.out.println("-------抛出异常时执行--------");}
public void afterReturn(){System.out.println("--------返回值之后执行--------");}
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
System.out.println("--------执行方法之前执行--------");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("--------执行方法之后执行--------");
return proceed;
}
}
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-4.0.xsd">
<bean id="userService" class="com.qfedu.edu.aop.config.UserService" />
<bean id="aop" class="com.qfedu.edu.aop.config.Aop" />
<aop:config>
<aop:pointcut id="pt" expression="execution(* com.qfedu.edu.aop.config.*.*(..))" />
<aop:aspect ref="aop">
<aop:before method="before" pointcut-ref="pt" />
<aop:after method="after" pointcut-ref="pt" />
<aop:after-returning method="afterReturn" pointcut-ref="pt" />
<aop:after-throwing method="afterThrowing" pointcut-ref="pt" />
<aop:around method="around" pointcut-ref="pt" />
</aop:aspect>
</aop:config>
</beans>
测试
public class Test {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean-aop-config.xml");
UserService bean = context.getBean(UserService.class);
bean.add();
}
}
注解实现AOP
Service
AOP类
@Aspect // 当前类是切面类
@Component
public class Aop {
// 指定切入点的表达式
@Pointcut(value = "execution(* com.qfedu.edu.aop.annotation.UserService.*(..))")
public void pt(){}
@Before(value = "pt()")
public void before() {System.out.println("--------执行目标方法之前--------");}
@After(value = "pt()")
public void after() {System.out.println("--------执行目标方法之后--------");}
@AfterThrowing(value = "pt()")
public void afterThrowing(){System.out.println("-------抛出异常时执行--------");}
@AfterReturning(value = "pt()")
public void afterReturn(){System.out.println("--------返回值之后执行--------");}
@Around(value = "pt()")
public Object around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable
{
System.out.println("--------执行方法之前执行--------");
Object proceed = proceedingJoinPoint.proceed();
System.out.println("--------执行方法之后执行--------");
return proceed;
}
}
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 指定注解扫描的包并打开Aop的自动代理 -->
<context:component-scan base-package="com.qfedu.edu.aop.annotation" />
<aop:aspectj-autoproxy />
</beans>
测试
Template
导包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.3.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
配置
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
<!-- 配置数据源 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql:///cd-java-fy-2301" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- 配置操作数据库的对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<!-- 配置Spring的注解扫描 -->
<context:component-scan base-package="com.qfedu.edu.dao" />
</beans>
DAO
@Repository
public class UserDAO {
@Resource
private JdbcTemplate jdbcTemplate;
public void add() {
jdbcTemplate.update("insert into t_user(username,password) values(?,?)","xiaobobo","123");
}
public void update() {
jdbcTemplate.update("update t_user set username=?","中国好");
}
}
测试
public class Test01 {
public static void main(String[] args){
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("classpath:bean-dao.xml");
UserDAO userDAO = classPathXmlApplicationContext.getBean(UserDAO.class);
userDAO.add();
}
}