Spring
Spring套餐
Spring&SpringMvc:承上启下的作用
SpringBoot:快速开发的脚手架,约定大于配置。
SpringCloud:基于SpringBoot开发
IOC理论
在之前的业务中用户的需求会影响我们的代码,我们会根据用户的需求改变我们的代码!如果程序代码量大同时昂贵,我们使用一个set接口实现,程序员不用管理系统的创建,系统的耦合性大大降低,注重在业务的实现上:
//UserServiceImpl
public class UserServiceImpl implements UserService{
private UserDao userDao;
//利用set动态实现值的注入
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
public void getUser() {
userDao.getUser();
}
}
//Test.java
public class MyTest {
public static void main(String[] args) {
UserServiceImpl userService = new UserServiceImpl();
userService.setUserDao(new UserDaoImpl()); //利用new来进行选择,不接触Dao层
userService.getUser();
}
}
IOC本质
主动权的转义,从业务层转到用户层。控制反转IOC是一种设计思想,DL是实现IOC的一种方法。控制反转是通过表述(xml或注解)并通过第三方去获取特定对象,再spring中实现反转的是IOC,方式是依赖注入。
HelloSpring
我们彻底不用修改程序,只要在xml中修改即可。
<?xml version="1.0" encoding="UTF-8" ?>
<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.xsd">
<bean id="mysqlImpl" class="com.dyd.dao.UserDaoIMysqlImpl"/>
<bean id="Impl" class="com.dyd.dao.UserDaoImpl"/>
<!--
ref:引用Spring容器中创好的对象
value:具体的值,基本的类型
-->
<bean id="UserServiceImpl" class="com.dyd.service.UserServiceImpl">
<property name="userDao" ref="mysqlImpl"/>
</bean>
</beans>
在用户层直接对xml进行解析获取bean即可使用。
import com.dyd.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取applicationcontext
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//直接get
UserServiceImpl userServiceImpl = (UserServiceImpl) context.getBean("UserServiceImpl");
userServiceImpl.getUser();
}
}
IOC创建对象方式
有参构造的方式,在构造的时候已经初始化了。
<!-- 使用下标 -->
<bean id="hello" class="com.dyd.pojo.Hello">
<constructor-arg index="0" value="Spring"></constructor-arg>
</bean>
<!-- 使用类型 -->
<bean id="hello" class="com.dyd.pojo.Hello">
<constructor-arg type="java.lang.String" value="Spring"></constructor-arg>
</bean>
<!-- 使用姓名 -->
<bean id="hello" class="com.dyd.pojo.Hello">
<constructor-arg name="name" value="Spring"></constructor-arg>
</bean>
Spring配置文件
别名
<bean id="hello" class="com.dyd.pojo.Hello">
<property name="str" value="Spring"/>
</bean>
<alias name="hello" alias="hello2"/>
Bean配置
<!--
id=变量名
class=bean所包含对象的名称
name=别名
class=new 的对象
property 相当于给对象设置一个值
-->
<bean id="hello" class="com.dyd.pojo.Hello" name="hello2">
<property name="str" value="Spring"/>
</bean>
Import
将不同的bean文件合并为总的配置合并即可。
<import resource="beans1.xml"/>
<import resource="beans2.xml"/>
<import resource="beans3.xml"/>
<import resource="beans4.xml"/>
依赖注入
<?xml version="1.0" encoding="UTF-8" ?>
<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.xsd">
<bean id="address" class="com.dyd.pojo.Address">
<property name="address" value="cppu"/>
</bean>
<bean id="student" class="com.dyd.pojo.Student">
<!--通过value注入-->
<property name="name" value="dyd"/>
<!--bean注入-->
<property name="address" ref="address"/>
<!--array-->
<property name="book">
<array>
<value>java</value>
<value>python</value>
<value>C++</value>
</array>
</property>
<!--List-->
<property name="hobbys">
<list>
<value>listen</value>
<value>view</value>
</list>
</property>
<!--Map-->
<property name="card">
<map>
<entry key="phone" value="12345678901"/>
<entry key="email" value="123456789@qq.com"/>
</map>
</property>
<!--Set-->
<property name="games">
<set>
<value>LOL</value>
<value>BOB</value>
</set>
</property>
<!--null-->
<property name="wife">
<null/>
</property>
<!--Properties-->
<property name="info">
<props>
<prop key="学号">2020203100</prop>
<prop key="性别">female</prop>
</props>
</property>
</bean>
</beans>
Bean作用域
单例模式:Spring默认机制,每次从容器中取得都是同一个东西。
<bean id="hello" class="com.dyd.pojo.Hello" scope="singleton">
<property name="str" value="Spring"/>
</bean>
原型模式:每次从容器中get时,都会产生新的对象。
<bean id="hello" class="com.dyd.pojo.Hello" scope="prototype">
<property name="str" value="Spring"/>
</bean>
自动装配
自动装配是Spring满足Bean依赖的一种方式!在Spring中有三种装配方式:
XML
1.Byname装配,通过name名字寻找和自己name一样的值:
<bean id="cat" class="com.dyd.pojo.Cat"/>
<bean id="dog" class="com.dyd.pojo.Dog"/>
<bean id="people" class="com.dyd.pojo.People" autowire="byName">
<property name="name" value="dyd"/>
</bean>
2.Byname装配,通过name名字寻找和自己对象属性类型相同的bean,类型要全局唯一:
<bean id="cat" class="com.dyd.pojo.Cat"/>
<bean id="dog" class="com.dyd.pojo.Dog"/>
<bean id="people" class="com.dyd.pojo.People" autowire="byType">
<property name="name" value="dyd"/>
</bean>
注解自动装配
1.导入约束:
<?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: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/context
http://www.springframework.org/schema/context/spring-context.xsd">
<context:annotation-config/>
</beans>
@Autowired:直接在属性上使用即可,默认通过bytype。
@Autowired
private Cat cat;
//允许为null
@Autowired(required = false)
private Dog dog;
@Resource:使用resource原生注解,默认先通过byname,然后用bytype实现。
@Resource
private Cat cat;
@Resource(name = "dog")
private Dog dog;
使用注解开发
属性注入:
xml:
<!--指定要扫描的包-->
<context:component-scan base-package="com.dyd.pojo"/>
pojo:
@Component
public class User {
@Value("dyd")
public String name;
public void setName(String name) {
this.name = name;
}
}
代理模式
静态代理
角色分析(不用去关注公共业务,实现业务分工):
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
package com.dyd.demo02;
public class UserProxy implements UserService{
private UserService userService;
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
//日志方法
public void log(String msg){
System.out.println("使用了"+msg+"方法");
}
}
理解图:
动态代理
动态代理和静态代理角色一样
动态代理是自动生成不是直接写好
动态代理分为两大类,基于接口的动态代理(JDK),基于类的动态代理(cglib)
一个动态代理类可以代理多个类,只要实现了同一个接口即可
万能模板
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Object target;
public void setRent(Object target) {
this.target= target;
}
//生成得到代理类
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//动态代理的本质为反射
Object result = method.invoke(target, args);
return result;
}
public void seeHouse(){
System.out.println("see house!");
}
}
业务实现
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理角色
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//通过调用程序处理角色来处理我们的接口对象
pih.setRent(host);
//动态生成proxy
Rent proxy = (Rent) pih.getProxy();
proxy.rent();
}
}
AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
使用Spring实现AOP需要导入依赖包!
log
BeforeLog:
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class BeforeLog implements MethodBeforeAdvice {
//method:要执行的目标对象的方法
//object:参数
//target:目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
AfterLog:
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回结果为"+returnValue);
}
}
XML
<?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"
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">
<bean id="userService" class="com.dyd.service.UserServiceImpl"/>
<bean id="beforelog" class="com.dyd.log.BeforeLog"/>
<bean id="afterlog" class="com.dyd.log.AfterLog"/>
<bean id="ownlog" class="com.dyd.ownlog.logs"/>
<!-- 第一个配置aop -->
<aop:config>
<!-- 切入点,execution(要执行的位置!) -->
<aop:pointcut id="pointcut" expression="execution(* com.dyd.service.UserServiceImpl.*(..))"/>
<!-- 执行环绕 -->
<aop:advisor advice-ref="beforelog" pointcut-ref="pointcut"/>
<aop:advisor advice-ref="afterlog" pointcut-ref="pointcut"/>
</aop:config>
<!-- 自定义方法aop -->
<aop:config>
<aop:aspect ref="ownlog">
<aop:pointcut id="point" expression="execution(* com.dyd.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:before method="after" pointcut-ref="point"/>
</aop:aspect>
</aop:config>
</beans>
MyBatis-Spring
导入相关jar包:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--Spring操作数据库的话,还需要一个spring-jdbc
-->
<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</build>
整合实现一:
1.引入Spring配置文件spring-dao.xml
<?xml version="1.0" encoding="GBK"?>
<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
https://www.springframework.org/schema/beans/spring-beans.xsd
</beans>
2.配置数据源替换mybaits的数据源
<!--DataSource:使用Spring的数据源替换Mybatis的配置 c3p0 dbcp druid
我们这里使用Spring提供的JDBC:-->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/mybatis?useSSL=false&useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="123456"/>
</bean>
3.配置SqlSessionFactory,关联MyBatis
<!--sqlSessionFactory-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<!--关联mybatis配置文件-->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
<property name="mapperLocations" value="classpath:com/kuang/mapper/*.xml"/>
</bean>
4.注册sqlSessionTemplate,关联sqlSessionFactory
<!--SqlSessionTemplate:就是我们使用的sqlSession-->
<bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate">
<!--只能使用构造器注入sqlSessionFactory,因为它没有set方法-->
<constructor-arg index="0" ref="sqlSessionFactory" />
</bean>
5.需要UserMapper接口的UserMapperImpl 实现类,私有化sqlSessionTemplate
public class UserMapperImpl implements UserMapper {
//我们的所有操作,都使用sqlSession来执行,在原来,现在都使用SqlsessionTemplate
private SqlSessionTemplate sqlSession;
public void setSqlSession(SqlSessionTemplate sqlSession) {
this.sqlSession = sqlSession;
}
public List<User> selectUser() {
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUser();
}
}
6.将自己写的实现类,注入到Spring配置文件中。
<bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
<property name="sqlSession" ref="sqlSession"/>
</bean>
7.测试使用即可。
@Test
public void test () throws IOException {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapper = context.getBean("userMapper", UserMapper.class);
for (User user : userMapper.selectUser()) {
System.out.println(user);
}
}
整合实现二:
1.将我们上面写的UserMapperImpl修改一下
public class UserMapperImpl extends SqlSessionDaoSupport implements UserMapper {
public List<User> selectUser() {
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
}
2.注入到Spring配置文件中。
<bean id="userMapper" class="com.kuang.mapper.UserMapperImpl">
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>xml
Spring事务
Spring在不同的事务管理API之上定义了一个抽象层,使得开发人员不必了解底层的事务管理API就可以使用Spring的事务管理机制。Spring支持编程式事务管理和声明式的事务管理。
XML
<?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:tx="http://www.springframework.org/schema/tx"
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
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd">
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<constructor-arg ref="dataSource" />
</bean>
<tx:advice id="txADVICE" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="*" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.dyd.mapper.*.*(..))"/>
<aop:advisor advice-ref="txADVICE" pointcut-ref="txPointCut"/>
</aop:config>
依赖包
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.0.RELEASE</version>
</dependency>
<!--junit单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!--spring AOP的包-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>4.3.7.RELEASE</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.2</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.2</version>
</dependency>
</dependencies>