Spring
2023-04-11 08:55:43 16 举报
AI智能生成
无
作者其他创作
大纲/内容
spring依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
ioc(Inversion of Control )控制反转
概念:反转了依赖关系的满足方式,由之前的自己创建依赖对象,变为由工厂推送。(变主动为被动,即反转
特点:解决了具有依赖关系的组件之间的强耦合,使得项目形态更加稳健
格式:
<bean id="userDAO" class="com.qf.spring.part1.injection.UserDaoImpl"></bean>
<!-- UserServiceImpl组件 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl">
<!-- 由spring为userDAO属性赋值,值为id="userDAO"的bean -->
<property name="userDAO" ref="userDAO"/>
</bean>
<bean id="userDAO" class="com.qf.spring.part1.injection.UserDaoImpl"></bean>
<!-- UserServiceImpl组件 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl">
<!-- 由spring为userDAO属性赋值,值为id="userDAO"的bean -->
<property name="userDAO" ref="userDAO"/>
</bean>
bean的生命周期
singleton:单例,ioc容器启动时就创建相应的bean对象,每次调用工厂,得到的都是同一个对象,ioc容器关闭时销毁
prototype:多例,需要时才创建相应的bean对象,每次调用工厂,都会创建新的对象,ioc关闭不会被销毁,会被gc回收
request: 为每一个HTTP请求创建一个全新的bean,当请求结束之后,该对象的生命周期即告结束。
session: 为每一个独立的session创建一个全新的bean对象,session结束之后,该bean对象的生命周期即告结束。
global session: global session只有应用在基于portlet的Web应用程序中才有意义,它映射到portlet的global范围的 session。
FactoryBean创建复杂对象
public class MyFactoryBean implements FactoryBean<Connection> {
Connection connection = null;
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/java2205", "root", "root");
return connection;
}
@Override
public Class<?> getObjectType() {
return connection.getClass();
}
@Override
public boolean isSingleton() {
return false;
}
}
Connection connection = null;
@Override
public Connection getObject() throws Exception {
Class.forName("com.mysql.jdbc.Driver");
connection = DriverManager.getConnection
("jdbc:mysql://localhost:3306/java2205", "root", "root");
return connection;
}
@Override
public Class<?> getObjectType() {
return connection.getClass();
}
@Override
public boolean isSingleton() {
return false;
}
}
DI(Dependency Injection)依赖注入
概念:在Spring创建对象的同时,为其属性赋值,称之为依赖注入
setget注入:
<bean id="bean01" class="com.wsk.bean.Bean01">
<property name="id" value="1"/>
<property name="name" value="李四"/>
<property name="array">
<array>
<value>1</value>
<value>12</value>
<value>33</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<property name="set">
<set>
<value>12</value>
<value>66</value>
<value>88</value>
</set>
</property>
<property name="map">
<map>
<entry key="1" value="李四"/>
<entry key="2" value="王五"/>
<entry key="3" value="赵六"/>
</map>
</property>
<property name="properties">
<props>
<prop key="1">666</prop>
<prop key="2">123</prop>
<prop key="3">赵六</prop>
<prop key="4">李四</prop>
</props>
</property>
</bean>
<bean id="bean01" class="com.wsk.bean.Bean01">
<property name="id" value="1"/>
<property name="name" value="李四"/>
<property name="array">
<array>
<value>1</value>
<value>12</value>
<value>33</value>
</array>
</property>
<property name="list">
<list>
<value>张三</value>
<value>李四</value>
<value>王五</value>
</list>
</property>
<property name="set">
<set>
<value>12</value>
<value>66</value>
<value>88</value>
</set>
</property>
<property name="map">
<map>
<entry key="1" value="李四"/>
<entry key="2" value="王五"/>
<entry key="3" value="赵六"/>
</map>
</property>
<property name="properties">
<props>
<prop key="1">666</prop>
<prop key="2">123</prop>
<prop key="3">赵六</prop>
<prop key="4">李四</prop>
</props>
</property>
</bean>
构造器注入:
<bean id="bean02" class="com.wsk.bean.Bean02">
<constructor-arg name="id" value="1"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg name="birth" ref="d1"/>
</bean>
<bean id="bean02" class="com.wsk.bean.Bean02">
<constructor-arg name="id" value="1"/>
<constructor-arg index="1" value="张三"/>
<constructor-arg name="birth" ref="d1"/>
</bean>
自动注入
根据类型:
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 为UserServiceImpl中的属性基于类型自动注入值 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byType"></bean>
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 为UserServiceImpl中的属性基于类型自动注入值 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byType"></bean>
根据名字:
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 会根据属性的名字去搜寻所以bean的id,找到并注入 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byName"></bean>
<bean id="userDao" class="com.qf.spring.part1.injection.UserDaoImpl" />
<!-- 会根据属性的名字去搜寻所以bean的id,找到并注入 -->
<bean id="userService" class="com.qf.spring.part1.injection.UserServiceImpl" autowire="byName"></bean>
注解注入
@Controller:将对应的类注册到ioc,用在controller层
@Service:将对应的类注册到ioc,用在service层
@Repository:将对应的类注册到ioc,用在dao层
@Component:将对应的类注册到ioc,用在三层结构以外的代码
@Autowired:默认根据类型自动注入
@Resource(name = ""):根据bean的名字自动注入
@Autowired
@Qualifier(""):
效果等同于@Resource(name = "")
@Qualifier(""):
效果等同于@Resource(name = "")
代理设计模式
概念:将核心功能与辅助功能(事务、日志、性能监控代码)分离,达到核心业务功能更纯粹、辅助业务功能可复用。
特点:在不改变核心代码的情况下,添加辅助功能。(无入侵)
引入AOP相关依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
静态代理设计模式
- 代理类 = 实现原始类相同接口 + 添加辅助功能 + 调用原始类的业务方法。
- 静态代理的问题
- 代理类数量过多,不利于项目的管理。
- 多个代理类的辅助功能代码冗余,修改时,维护性差。
- 静态代理的问题
- 代理类数量过多,不利于项目的管理。
- 多个代理类的辅助功能代码冗余,修改时,维护性差。
动态代理设计模式
JDK动态代理实现(基于接口):
FruitService fruitService = new FruitServiceImpl();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JdkProxy前置条件");
method.invoke(fruitService, args);
return null;
}
};
FruitService proxy = (FruitService) Proxy.newProxyInstance
(JdkProxyTest.class.getClassLoader(), fruitService.getClass().getInterfaces(),
invocationHandler);
FruitService fruitService = new FruitServiceImpl();
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("JdkProxy前置条件");
method.invoke(fruitService, args);
return null;
}
};
FruitService proxy = (FruitService) Proxy.newProxyInstance
(JdkProxyTest.class.getClassLoader(), fruitService.getClass().getInterfaces(),
invocationHandler);
CGlib动态代理实现(基于继承):
GoodsServiceImpl goodsService = new GoodsServiceImpl();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(goodsService.getClass());
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
method.invoke(goodsService, args);
System.out.println("CglibProxy后置通知...");
return null;
}
});
GoodsServiceImpl proxy = (GoodsServiceImpl) enhancer.create();
GoodsServiceImpl goodsService = new GoodsServiceImpl();
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(goodsService.getClass());
enhancer.setCallback(new InvocationHandler() {
@Override
public Object invoke(Object o, Method method, Object[] objects) throws Throwable {
method.invoke(goodsService, args);
System.out.println("CglibProxy后置通知...");
return null;
}
});
GoodsServiceImpl proxy = (GoodsServiceImpl) enhancer.create();
JDK和CGLib的区别:
jdk是面向有接口的类,而没有接口的类需要用CGLib
jdk是面向有接口的类,而没有接口的类需要用CGLib
AOP开发术语
连接点(Joinpoint):连接点是程序类中客观存在的方法,可被Spring拦截并切入内容。所有的方法
切入点(Pointcut):被Spring切入连接点。要进行增强或通知的方法
通知、增强(Advice):可以为切入点添加额外功能,分为:前置通知、后置通知、异常通知、环绕通知等。
切面(Aspect):由切点和通知组成,将横切逻辑织入切面所指定的连接点中。
通知
设置通知的方式
配置文件配置通知
<!--原始对象-->
<bean id="us" class="com.qf.aaron.aop.basic.UserServiceImpl" />
<!--辅助对象-->
<bean id="myAdvice" class="com.qf.aaron.aop.basic.MyAdvice" />
<bean id="us" class="com.qf.aaron.aop.basic.UserServiceImpl" />
<!--辅助对象-->
<bean id="myAdvice" class="com.qf.aaron.aop.basic.MyAdvice" />
<aop:config>
<!--切点-->
<aop:pointcut id="myPointCut" expression="execution(* save())" />
<!--组装切面 -->
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" />
</aop:config>
<!--切点-->
<aop:pointcut id="myPointCut" expression="execution(* save())" />
<!--组装切面 -->
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPointCut" />
</aop:config>
<aop:config>
<aop:pointcut id="myPointCut1" expression="execution(* com.wsk.service.StudentService.getAll())"/>
<aop:pointcut id="myPointCut2" expression="execution(* com.wsk.service.StudentService.getOne())"/>
<aop:pointcut id="myPointCut3" expression="execution(* com.wsk.service.StudentService.add())"/>
<aop:pointcut id="myPointCut4" expression="execution(* com.wsk.service.StudentService.delete())"/>
<aop:pointcut id="myPointCut5" expression="execution(* com.wsk.service.StudentService.upDate())"/>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="myPointCut1"/>
<aop:after method="after" pointcut-ref="myPointCut2"/>
<aop:after-returning method="returning" pointcut-ref="myPointCut3"/>
<aop:after-throwing method="ex" pointcut-ref="myPointCut4"/>
<aop:around method="around" pointcut-ref="myPointCut5"/>
</aop:aspect>
</aop:config>
<aop:pointcut id="myPointCut1" expression="execution(* com.wsk.service.StudentService.getAll())"/>
<aop:pointcut id="myPointCut2" expression="execution(* com.wsk.service.StudentService.getOne())"/>
<aop:pointcut id="myPointCut3" expression="execution(* com.wsk.service.StudentService.add())"/>
<aop:pointcut id="myPointCut4" expression="execution(* com.wsk.service.StudentService.delete())"/>
<aop:pointcut id="myPointCut5" expression="execution(* com.wsk.service.StudentService.upDate())"/>
<aop:aspect ref="myAspect">
<aop:before method="before" pointcut-ref="myPointCut1"/>
<aop:after method="after" pointcut-ref="myPointCut2"/>
<aop:after-returning method="returning" pointcut-ref="myPointCut3"/>
<aop:after-throwing method="ex" pointcut-ref="myPointCut4"/>
<aop:around method="around" pointcut-ref="myPointCut5"/>
</aop:aspect>
</aop:config>
注解配置通知
@Component
@Aspect
public class MyAspect01 {
@Pointcut("execution(* com.wsk.service.AnimalService.getAll())")
public void m1() {}
@Pointcut("execution(* com.wsk.service.AnimalService.getOne())")
public void m2() {}
@Pointcut("execution(* com.wsk.service.AnimalService.add())")
public void m3() {}
@Pointcut("execution(* com.wsk.service.AnimalService.delete())")
public void m4() {}
@Pointcut("execution(* com.wsk.service.AnimalService.upDate())")
public void m5() {}
@Before("m1()")
public void before() {
System.out.println("01前置条件执行了...");
}
@After("m2()")
public void after() {
System.out.println("01后置条件执行了...");
}
@AfterReturning("m3()")
public void returning() {
System.out.println("01返回通知执行了...");
}
@AfterThrowing("m4()")
public void ex() {
System.out.println("01异常通知执行了...");
}
@Around("m5()")
public void around(ProceedingJoinPoint pjp) {
long start = System.currentTimeMillis();
try {
pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("01环绕通知执行了... 此接口花费时间为:"+(end-start)+"毫秒");
}
}
@Aspect
public class MyAspect01 {
@Pointcut("execution(* com.wsk.service.AnimalService.getAll())")
public void m1() {}
@Pointcut("execution(* com.wsk.service.AnimalService.getOne())")
public void m2() {}
@Pointcut("execution(* com.wsk.service.AnimalService.add())")
public void m3() {}
@Pointcut("execution(* com.wsk.service.AnimalService.delete())")
public void m4() {}
@Pointcut("execution(* com.wsk.service.AnimalService.upDate())")
public void m5() {}
@Before("m1()")
public void before() {
System.out.println("01前置条件执行了...");
}
@After("m2()")
public void after() {
System.out.println("01后置条件执行了...");
}
@AfterReturning("m3()")
public void returning() {
System.out.println("01返回通知执行了...");
}
@AfterThrowing("m4()")
public void ex() {
System.out.println("01异常通知执行了...");
}
@Around("m5()")
public void around(ProceedingJoinPoint pjp) {
long start = System.currentTimeMillis();
try {
pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("01环绕通知执行了... 此接口花费时间为:"+(end-start)+"毫秒");
}
}
通知的分类
前置通知:MethodBeforeAdvice
后置通知:AfterAdvice
后置通知:AfterReturningAdvice //有异常不执行,方法会因异常而结束,无返回值
异常通知:ThrowsAdvice
环绕通知:MethodInterceptor
后置通知:AfterAdvice
后置通知:AfterReturningAdvice //有异常不执行,方法会因异常而结束,无返回值
异常通知:ThrowsAdvice
环绕通知:MethodInterceptor
事务
引入依赖:
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.1.6.RELEASE</version>
</dependency>
acid:数据库事务正确执行的四个基本要素的缩写
a:atomicity原子性
c:consistency一致性
i:isolation隔离性
d:durability持久性
属性
isolation 隔离级别
read-uncommited读未提交
read-commited读已提交 (Oracle数据库默认的隔离级别)
repeatable-read可重复读 (MySQL数据库默认的隔离级别)
serialized-read序列化读 串行化读
propagation 传播行为
int PROPAGATION_REQUIRED = 0; //支持当前事务,如果不存在,就新建一个
如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入改事务
如果当前没有事务,就创建一个新事务;如果当前存在事务,就加入改事务
int PROPAGATION_SUPPORTS = 1; //支持当前事务,如果不存在,就不使用事务
如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行
如果当前存在事务,就加入该事务;如果当前不存在事务,就以非事务执行
int PROPAGATION_MANDATORY = 2; //支持当前事务,如果不存在,就抛出异常
如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常
如果当前存在事务,就加入该事务;如果当前不存在事务,就抛出异常
int PROPAGATION_REQUIRES_NEW = 3;//如果有事务存在,挂起当前事务,创建一个新的事物
无论当前存不存在事务,都创建新事务
无论当前存不存在事务,都创建新事务
int PROPAGATION_NOT_SUPPORTED = 4;//以非事务方式运行,如果有事务存在,挂起当前事务
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起
int PROPAGATION_NEVER = 5;//以非事务方式运行,如果有事务存在,就抛出异常
以非事务方式执行,如果当前存在事务,则抛出异常
以非事务方式执行,如果当前存在事务,则抛出异常
int PROPAGATION_NESTED = 6;//如果有事务存在,则嵌套事务执行
readonly 读写性
true:只读,可提高查询效率。(适合查询)
false:可读可写。 (默认值)(适合增删改)
timeout 事务超时时间
rollback-for 回滚属性
no-rollback-for 让运行时异常抛出时不回滚
配置文件配置
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="tx">
<tx:attributes>
<tx:method name="add"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.wsk.service.UserService.add())"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
<property name="dataSource" ref="ds"/>
</bean>
<tx:advice id="txAdvice" transaction-manager="tx">
<tx:attributes>
<tx:method name="add"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.wsk.service.UserService.add())"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
</aop:config>
注解配置
@Transactional(isolation = Isolation.DEFAULT) 括号里写属性
配置文件:
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<tx:annotation-driven transaction-manager="tx"/>
<context:component-scan base-package="com.wsk"/>
配置文件:
<bean id="tx" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="ds"/>
</bean>
<tx:annotation-driven transaction-manager="tx"/>
<context:component-scan base-package="com.wsk"/>
事务管理分类
声明式事务管理
配置文件
注解
编程式事务管理
template.execute()
0 条评论
下一页