<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.7.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.7.RELEASE</version> </dependency>
spring优点:
-
spring是一个开源的免费框架
-
spring是一个轻量级、非入侵式的框架
-
控制反转(IOC)、面向切面编程(AOP)
-
支持事务处理
总结:spring是一个轻量级的控制反转和面向切面编程的框架。
组成
2.IOC理论推导
1.UserDao接口
2.UserDaoImpl实现类
3.UserService业务接口
4.UserServiceImpl 业务实现类
使用set接口实现。
public class UserServiceImpl implements UserService { private UserDao userDao; public void getUser() { userDao.getUser(); } //使用set实现动态的值注入 public void setUserDao(UserDao userDao){ this.userDao = userDao; } }
-
使用set注入,不在关注对象的创建,耦合性降低,对象的创建交给了第三方,IOC原型。
IOC本质
控制反转IOC是一种设计思想,DI(依赖注入)是一种IOC的实现方法。控制反转是一种通过描述(xml或者注解)并通过第三方生产获取特定对象的方式,在spring中实现控制反转的IOC容器,实现方法是依赖注入。
IOC创建对象的方式
1.使用无参构造创建对象(默认)
2.使用有参构造创建对象
在配置文件加载时,容器中管理的对象就已经初始化了。
3.spring配置
别名
<alias name="hello" alias="HelloNew"/>
使用别名,也可以通过原来的名字创建对象。
import
<import resource="beans.xml"/>
可以将多个配置文件导入合并为一个配置文件,使用时直接用总配置即可。
4.依赖注入
4.1、构造器注入
<constructor-arg name="name" value="kerwin"/>
4.2、set方式注入
-
依赖注入:set注入
-
依赖:bean对象的创建依赖于容器
-
注入:bean对象的所有属性由容器注入
-
1.实体类
public class Student { private String name; private String[] books; private Address address; private List<String> hobbys; private Map<String,String> card; private Set<String> games; private Properties info; private String wife; }
public class Address { private String address; }
2.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 https://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="address" class="com.kerwin.pojo.Address"> <property name="address" value="深圳"/> </bean> <bean id="student" class="com.kerwin.pojo.Student"> <!--1.普通类型注入 value--> <property name="name" value="kerwin"/> <!--2.bean注入 ref--> <property name="address" ref="address"/> <!--3.array--> <property name="books"> <array> <value>java编程思想</value> <value>spring源码</value> </array> </property> <!--4.list--> <property name="hobbys"> <list> <value>唱</value> <value>跳</value> <value>rap</value> </list> </property> <!--5.map--> <property name="card"> <map> <entry key="身份证" value="111"/> <entry key="银行卡" value="122"/> </map> </property> <!--6.set--> <property name="games"> <set> <value>LOL</value> <value>csgo</value> </set> </property> <!--7.null--> <property name="wife"> <null></null> </property> <!--8.properties--> <property name="info"> <props> <prop key="工号">0139</prop> <prop key="sex">man</prop> </props> </property> </bean> </beans>
3.测试类
public class MyTest { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); Student student = (Student) context.getBean("student"); System.out.println(student); } }
4.3、扩展方式注入
p命名空间注入,可以直接注入属性值。
c命名空间注入,通过构造器注入。
需要导入以下约束。
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
使用:
<bean id="address2" class="com.kerwin.pojo.Address" p:address="西安"/> <bean id="address3" class="com.kerwin.pojo.Address" c:address="成都"/>
5.bean作用域
(Default) Scopes a single bean definition to a single object instance for each Spring IoC container. 单例 | |
---|---|
Scopes a single bean definition to any number of object instances. 原型模式,创建新对象 | |
Scopes a single bean definition to the lifecycle of a single HTTP request. That is, each HTTP request has its own instance of a bean created off the back of a single bean definition. Only valid in the context of a web-aware Spring ApplicationContext . |
|
Scopes a single bean definition to the lifecycle of an HTTP Session . Only valid in the context of a web-aware Spring ApplicationContext . |
|
Scopes a single bean definition to the lifecycle of a ServletContext . Only valid in the context of a web-aware Spring ApplicationContext . |
|
Scopes a single bean definition to the lifecycle of a WebSocket . Only valid in the context of a web-aware Spring ApplicationContext . |
request、session、application 在web开发中使用。
6.bean的自动装配
spring会在上下文中自动寻找,并自动给bean装配属性。
6.1环境搭建:
一个人有两只宠物。
public class Cat { public void shout(){ System.out.println("miao~"); } } public class Dog { public void shout(){ System.out.println("wang~"); } } public class People { private String name; private Cat cat; private Dog dog; }
6.2ByName自动装配
需要保证所有beanId唯一,需要和属性set方法值一致
<bean id="cat" class="com.kerwin.pojo.Cat"/> <bean id="dog" class="com.kerwin.pojo.Dog"/> <!--byName:自动在容器中查找和自己对象set方法后面的值对应的bean id--> <bean id="people" class="com.kerwin.pojo.People" autowire="byName"> <property name="name" value="kerwin"/> </bean>
6.3ByType自动装配
需要保证bean的Class唯一,bean需要和属性类型一致
<!--byType:自动在容器中查找和自己对象属性类型相同的bean-->
<bean id="people2" class="com.kerwin.pojo.People" autowire="byType"> <property name="name" value="Jax"/> </bean> <bean class="com.kerwin.pojo.Dog"/> <bean class="com.kerwin.pojo.Cat"/>
6.4使用注解完成自动装配
1.导入约束
2.配置注解支持
<?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 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:component-scan base-package="com.kerwin.pojo"/> <!--开启注解--> <context:annotation-config/> <bean id="cat" class="com.kerwin.pojo.Cat"/> <bean id="dog" class="com.kerwin.pojo.Dog"/> <bean id="people" class="com.kerwin.pojo.People"/> </beans>
Autowired直接在属性上/set方法上使用,默认按照类型查找
@Autowired可以和@Qualifier(value="XXX")配合使用,找到唯一的bean注入
@Resource//先按照名字查找,找不到再按照类型查找
7.注解开发
@Component衍生注解,分层标识,功能一样
-
dao 【@Repository】
-
service 【@ervice】
-
controller【@Controller】
配置类:
@Configuration//也会被注册到spring容器中 public class MyConfig { //注册一个bean //方法名==bean标签的id属性 //返回值==bean标签的class属性 @Bean public User gerUser(){ return new User(); } }
实体类:
@Data//lombok注解 @Component public class User { @Value("kerwin") private String name; }
测试类:
public class MyTest { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class); User user = (User) context.getBean("gerUser"); System.out.println(user.getName()); } }
8.代理模式
SpringAOP底层
代理模式分类:
-
静态代理
-
动态代理
8.1、静态代理
-
抽象角色:一般使用接口或抽象类
-
真实角色:被代理的角色
-
代理角色:代理真实角色,一般会有一些附属操作
-
客户:访问代理对象的角色
示例: 租房、房东、中介、客户
代码:
抽象角色
public interface Rent { public void rent(); }
真实角色
public class Landlord implements Rent { public void rent() { System.out.println("房东出租房子"); } }
代理角色
public class Proxy implements Rent { private Landlord landlord; public Proxy() { } public Proxy(Landlord landlord) { this.landlord = landlord; } public void rent() { landlord.rent(); } public void seeHouse(){ System.out.println("中介带看房"); } public void fare(){ System.out.println("中介收费"); } }
客户
public class Client { public static void main(String[] args) { //房东,被代理类 Landlord landlord = new Landlord(); //代理,中介有附属操作 Proxy proxy = new Proxy(landlord); proxy.rent(); } }
代理模式好处:
-
可以使真实角色操作更纯粹,不关注公共业务
-
公共业务交给了代理角色,实现了业务分工
-
方便集中管理公共业务,便于扩展
缺点:
-
一个真实角色产生一个代理对象,代码量翻倍
8.2、动态代理
动态代理的代理类动态生成。
-
基于接口的动态代理 (JDK动态代理)
-
基于类的动态代理 (cglib)
优点:
-
一个动态代理类代理的是一个接口,一般对应一类业务
-
一个代理类可以代理多个类,只要实现同一个接口
public class ProxyInvo implements InvocationHandler { //被代理的接口 private Object target; public void setTarget(Object target) { this.target = target; } //生成代理类 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(),this); } //处理代理实例,返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { log(method.getName()); Object result = method.invoke(target, args); return result; } private void log(String method){ System.out.println("执行了"+method+"方法"); } }
public class Client { public static void main(String[] args) { //真实角色 Landlord landlord = new Landlord(); //代理角色,不存在 ProxyInvo proxyInvo = new ProxyInvo(); //设置要代理的类 proxyInvo.setTarget(landlord); //动态生成代理类 Rent proxy = (Rent) proxyInvo.getProxy(); proxy.rent(); } }
9.AOP
面向切面编程
1.基于xml的AOP
依赖:
<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver --> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.5</version> </dependency>
execution表达式
1、execution(): 表达式主体。
2、第一个*号:表示返回类型,号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
4、第二个*号:表示类名,号表示所有的类。
5、*(..):最后这个星号表示方法名,号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。
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: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 http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <bean id="userService" class="com.kerwin.service.UserServiceImpl"/> <bean id="log" class="com.kerwin.log.Log"/> <!--方法1:spring接口,配置AOP--> <aop:config> <!--切入点 execution(要执行的位置)--> <aop:pointcut id="pointcut" expression="execution(* com.kerwin.service.UserServiceImpl.*(..))"/> <aop:advisor advice-ref="log" pointcut-ref="pointcut"/> </aop:config> <!--方法2:自定义类--> <bean id="diy" class="com.kerwin.diy.DiyPointCut"/> <aop:config> <!--自定义切面--> <aop:aspect id="point" ref="diy"> <!--切入点--> <aop:pointcut id="point" expression="execution(* com.kerwin.service.UserServiceImpl.*(..))"/> <aop:before method="before" pointcut-ref="point"/> <aop:after method="after" pointcut-ref="point"/> </aop:aspect> </aop:config> </beans>
自定义类
public class DiyPointCut { public void before(){ System.out.println("方法执行前"); } public void after(){ System.out.println("方法执行后"); } }
2.注解开发AOP
约束信息:
<context:component-scan base-package="com.kerwin"/> <!--开启AOP注解支持,proxy-target-class默认为false,jdk, true 为cglib--> <aop:aspectj-autoproxy proxy-target-class="false"/>
DIY切面类
@Component @Aspect //标注此类为切面 public class AnnotationPointCut { @Before("execution(* com.kerwin.service.UserServiceImpl.*(..))") public void before(){ System.out.println("=======方法执行前======="); } @After("execution(* com.kerwin.service.UserServiceImpl.*(..))") public void after(){ System.out.println("=======方法执行后======="); } }
10、声明式事务
1.ACID
- 原子性(atomicity)
- 一致性(consistency)
- 隔离性(isolation)
- 持久性(durability)
2.spring事务管理
-
声明式事务:AOP
-
将事务管理代码从业务方法中分离出来,以声明的方式来实现事务管理。
-
将事务管理作为横切关注点,通过aop方法模块化。Spring中通过Spring AOP框架支持声明式事务管理。
-
- 倒入约束
xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd">
- 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" 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="search*" propagation="REQUIRED"/> <tx:method name="get" read-only="true"/> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
- 配置AOP
<!--配置aop织入事务--> <aop:config> <aop:pointcut id="txPointcut" expression="execution(* com.kerwin.mapper.*.*(..))"/> <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/> </aop:config>
- 倒入约束
-
编程式事务:需要在代码中进行事务管理