spring概述及IOC理论推导
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0modelVersion>
<groupId>com.lxfgroupId>
<artifactId>20200602-spring-studyartifactId>
<packaging>pompackaging>
<version>1.0-SNAPSHOTversion>
<modules>
<module>spring-01-iocmodule>
<module>spring-02-hellospringmodule>
<module>spring-04-dimodule>
<module>spring-05-Autowiredmodule>
<module>spring-06-annomodule>
<module>spring-07-appConfigmodule>
<module>spring-08-proxymodule>
<module>spring-09-aopmodule>
modules>
<dependencies>
<dependency>
<groupId>org.springframeworkgroupId>
<artifactId>spring-webmvcartifactId>
<version>5.2.0.RELEASEversion>
dependency>
<dependency>
<groupId>junitgroupId>
<artifactId>junitartifactId>
<version>4.12version>
dependency>
dependencies>
project>
实体类Hello:
package com.lxf.pojo;
public class Hello {
private String str;
public String getStr() {
return str;
}
public void setStr(String str) {
this.str = str;
}
@Override
public String toString() {
return "Hello{" +
"str='" + str + '\'' +
'}';
}
}
beans.xml(通常叫applicationContext.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="hello" class="com.lxf.pojo.Hello">
<property name="str" value="Spring" />
bean>
beans>
测试类MyTest:
import com.lxf.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取spring的上下文对象
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
//对象在spring管理,用直接取
Hello hello = (Hello) context.getBean("hello");
//或者Hello hello = context.getBean("hello",Hello.class);
//打印这个对象
System.out.println(hello);
}
}
实体类Address:
package com.lxf.pojo;
public class Address {
private String address;
public void setAddress(String address) {
this.address = address;
}
public String getAddress() {
return address;
}
@Override
public String toString() {
return "Address{" +
"address='" + address + '\'' +
'}';
}
}
实体类Student:
package com.lxf.pojo;
import java.util.*;
public class Student {
private String name;
private Address address;
private String[] books;
private List hobbys;
private Map card;
private Set game;
private String wife;
private Properties info;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
public String[] getBooks() {
return books;
}
public void setBooks(String[] books) {
this.books = books;
}
public List getHobbys() {
return hobbys;
}
public void setHobbys(List hobbys) {
this.hobbys = hobbys;
}
public Map getCard() {
return card;
}
public void setCard(Map card) {
this.card = card;
}
public Set getGame() {
return game;
}
public void setGame(Set game) {
this.game = game;
}
public String getWife() {
return wife;
}
public void setWife(String wife) {
this.wife = wife;
}
public Properties getInfo() {
return info;
}
public void setInfo(Properties info) {
this.info = info;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", address=" + address +
", books=" + Arrays.toString(books) +
", hobbys=" + hobbys +
", card=" + card +
", game=" + game +
", wife='" + wife + '\'' +
", info=" + info +
'}';
}
}
实体类User:
package com.lxf.pojo;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
beans.xml(通常叫applicationContext.xml):
<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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="address" class="com.lxf.pojo.Address">
<property name="address" value="中国"/>
bean>
<bean id="student" class="com.lxf.pojo.Student">
<property name="name" value="lxf"/>
<property name="address" ref="address"/>
<property name="books">
<array>
<value>红楼梦value>
<value>西游记value>
<value>三国演义value>
<value>水浒传value>
array>
property>
<property name="hobbys">
<list>
<value>听歌value>
<value>看电影value>
<value>打游戏value>
<value>打代码value>
list>
property>
<property name="card">
<map>
<entry key="身份证" value="1234567890"/>
<entry key="银行卡" value="9876543210"/>
map>
property>
<property name="game">
<set>
<value>LOLvalue>
<value>COCvalue>
<value>BOBvalue>
set>
property>
<property name="wife">
<null/>
property>
<property name="info">
<props>
<prop key="Num">20190525prop>
<prop key="url">男prop>
<prop key="username">rootprop>
<prop key="password">123456prop>
props>
property>
bean>
beans>
实体类User:
package com.lxf.pojo;
public class User {
private String name;//名字
private int age;//年龄
private String sex;//性别
public User(String name, int age, String sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
", sex='" + sex + '\'' +
'}';
}
}
userbeans.xml(通常叫applicationContext.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
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.lxf.pojo.User">
<constructor-arg index="0" value="刘一手">constructor-arg>
<constructor-arg index="1" value="18">constructor-arg>
<constructor-arg index="2" value="男">constructor-arg>
bean>
<bean id="user" class="com.lxf.pojo.User">
<constructor-arg type="java.lang.String" value="刘一手">constructor-arg>
<constructor-arg type="java.lang.Integer" value="18">constructor-arg>
<constructor-arg type="java.lang.String" value="男">constructor-arg>
bean>
beans>
实体类User:
package com.lxf.pojo;
public class User {
private String name;
private int age;
public User() {
}
public User(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
userbeans.xml(通常叫applicationContext.xml):
<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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="user" class="com.lxf.pojo.User" p:name="刘一手" p:age="18" />
<bean id="user2" class="com.lxf.pojo.User" c:_0="刘二手" c:_1="19"/>
beans>
实体类cat:
package com.lxf.pojo;
public class Cat {
public void shout(){
System.out.println("miao~");
}
}
实体类dog:
package com.lxf.pojo;
public class Dog {
public void shout(){
System.out.println("wang~");
}
}
实体类People:
package com.lxf.pojo;
import org.springframework.beans.factory.annotation.Autowired;
public class People {
@Autowired
private Cat cat;
@Autowired //先bytype,后byname,spring注解
//@Resource,先byname,后bytype,java注解
private Dog dog;
private String name;
public Cat getCat() {
return cat;
}
public void setCat(Cat cat) {
this.cat = cat;
}
public Dog getDog() {
return dog;
}
public void setDog(Dog dog) {
this.dog = dog;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "People{" +
"cat=" + cat +
", dog=" + dog +
", name='" + name + '\'' +
'}';
}
}
beans.xml(一般名为:applicationContext.xml)
<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">
<bean id="cat3" class="com.lxf.pojo.Cat"/>
<bean id="cat" class="com.lxf.pojo.Cat"/>
<bean id="dog" class="com.lxf.pojo.Dog"/>
<bean id="people" class="com.lxf.pojo.People"/>
<context:annotation-config />
beans>
测试类MyTest:
import com.lxf.pojo.People;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取上下文对象
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
//从容器中取到people对象
People people = context.getBean("people", People.class);
//调用(已装载)
people.getDog().shout();
people.getCat().shout();
System.out.println("people = " + people);
}
}
controller层:
package com.lxf.controller;
import org.springframework.stereotype.Controller;
@Controller
public class UserController {
}
Dao层:
package com.lxf.dao;
import org.springframework.stereotype.Repository;
@Repository
public class UserDao {
}
pojo层:
package com.lxf.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
//等于在容器中注册
@Component
//@Scope(value = "prototype")
@Scope(scopeName = "singleton")
public class User {
@Value("刘一手")
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
service层:
package com.lxf.service;
import org.springframework.stereotype.Service;
@Service
public class UserService {
}
application.xml:
<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">
<context:annotation-config />
<context:component-scan base-package="com.lxf"/>
beans>
测试类MyTest:
import com.lxf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Mytest {
public static void main(String[] args) {
//获取上下文对象
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
//获取User
User user=context.getBean("user", User.class);
//打印结果
System.out.println("user.name = " + user.getName());
}
}
config类:
package com.lxf.config;
import com.lxf.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
//@Import(User.class) //导入合并其他配置类,类似于配置文件中的 inculde 标签
//@ComponentScan("com.lxf.pojo") //扫描包
public class LxfConfig {
@Bean
public User getUser(){
return new User();
}
}
User实体类:
package com.lxf.pojo;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("lxf")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
测试类MyTest:
import com.lxf.config.LxfConfig;
import com.lxf.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MyTest {
public static void main(String[] args) {
//获取上下文对象
ApplicationContext context=new AnnotationConfigApplicationContext(LxfConfig.class);
//获取User
User user = (User) context.getBean("getUser");
//打印结果
System.out.println(user.getName());
}
}
SpringAOP中,通过Advice定义横切逻辑,Spring中支持5种类型的Advice:
理解:就是对动态代理的进一步封装,springAop代理真实类对象,然后对进行真实类对象切入,根据切入点分了5种类型通知(顺序、返回值、异常),可自己选择添加与否。
pom.xml的依赖:
<dependency>
<groupId>org.aspectjgroupId>
<artifactId>aspectjweaverartifactId>
<version>1.9.4version>
dependency>
了解动态代理对理解AOP有很好的帮助作用:静态代理与动态代理
application.xml:
<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.lxf.service.UserServiceImpl"/>
<bean id="log" class="com.lxf.log.Log"/>
<bean id="afterLog" class="com.lxf.log.AfterLog"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.lxf.service.UserServiceImpl.*(..))"/>
<aop:advisor advice-ref="log" pointcut-ref="pointcut" />
<aop:advisor advice-ref="afterLog" pointcut-ref="pointcut" />
aop:config>
<bean id="diy" class="com.lxf.diy.DiyPointCut"/>
<aop:config>
<aop:aspect ref="diy">
<aop:pointcut id="point" expression="execution(* com.lxf.service.UserServiceImpl.*(..))"/>
<aop:before method="before" pointcut-ref="point"/>
<aop:after method="after" pointcut-ref="point"/>
aop:aspect>
aop:config>
<bean id="annotationPointCut" class="com.lxf.diy.AnnotationPointCut"/>
<aop:aspectj-autoproxy/>
beans>
service层:
Userservice接口:
package com.lxf.service;
public interface UserService {
void add();
void delete();
void update();
void query();
}
UserserviceImpl实现类:
package com.lxf.service;
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一个用户");
}
@Override
public void delete() {
System.out.println("删除了一个用户");
}
@Override
public void update() {
System.out.println("更新了一个用户");
}
@Override
public void query() {
System.out.println("查询了一个用户");
}
}
log包:
Log类:
package com.lxf.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class Log implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
AfterLog类:
package com.lxf.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
public class AfterLog implements AfterReturningAdvice {
//returnValue:返回值
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("执行了"+method.getName()+"返回结果为:"+returnValue);
}
}
diy包:
自定义DiyPointCut类:
package com.lxf.diy;
public class DiyPointCut {
public void before(){
System.out.println("=================方法执行前===================");
}
public void after(){
System.out.println("=================方法执行后===================");
}
}
diy包:
AnnotationPointCut包
package com.lxf.diy;
//方式三:注解实现
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class AnnotationPointCut {
@Before("execution(* com.lxf.service.UserServiceImpl.*(..))")
public void before(){
System.out.println("==========方法执行前===========");
}
@After("execution(* com.lxf.service.UserServiceImpl.*(..))")
public void after(){
System.out.println("==========方法执行后===========");
}
//在环绕中,可以给定一个参数,代表要获取处理切入的点
@Around("execution(* com.lxf.service.UserServiceImpl.*(..))")
public void round(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("==========环绕前===========");
//System.out.println("signatrue"+ joinPoint.getSignature());
//执行方法
joinPoint.proceed();
System.out.println("==========环绕后==========");
}
}
事务的ACID原则:
** REQUIRED:**支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。 (默认值)
SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方式执行。
MANDATORY:支持当前事务,如果当前没有事务,就抛出异常。
REQUIRES_NEW:新建事务,如果当前存在事务,把当前事务挂起。
NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
NESTED:支持当前事务,如果当前事务存在,则执行一个嵌套事务,如果当前没有事务,就新建一个事务。
DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是READ_COMMITTED。
READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读,不可重复读和幻读,因此很少使用该隔离级别。比如PostgreSQL实际上并没有此级别。
READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。该级别可以防止脏读和不可重复读。
SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
<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="add" propagation="REQUIRED" />
<tx:method name="delete" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="query" read-only="true"/>
<tx:method name="*" propagation="REQUIRED"/>
tx:attributes>
tx:advice>
<aop:config>
<aop:pointcut id="txPointCut" expression="execution(* com.lxf.mapper.*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointCut"/>
aop:config>
思考:
为什么配置事务?