官网:https://spring.io/projects/spring-framework#overview
org.springframework
spring-web
5.2.0.RELEASE
org.springframework
spring-jdbc
5.2.0.RELEASE
总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
在Spring的官网有这个介绍:现代化的Java开发!说白了就是基于Spring的开发!
1、UserDao接口
2、UserDaoImpl实现类
3、UserService业务接口
4、UserServiceImpl 业务实现类
private UserDao userDao;
public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}
这种思想,从本质上解决了问题,我们程序猿不再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注在业务的实现上!这是IOC的原型!
控制反转IOC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IOC的一种方法,也有人认为DI只是IOC的另一张说法。没有IOC的程序中,我们使用面向对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IOC容器,其实现方法是依赖注入(Dependency Injection,DI)。
package com.kuang.pojo;
/**
* @Author panghl
* @Date 2021/3/16 21:27
* @Description TODO
**/
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 + '\'' +
'}';
}
}
import com.kuang.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/16 21:31
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
//获取Spring的上下文对象!
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在Spring中的管理,我们要使用,直接去里面取出来就可以了!
Hello hello = (Hello)context.getBean("hello");
System.out.println(hello.getStr());
}
}
ok,到了现在,我们彻底不用在程序中去改动了,要实现不同的操作,只需在xml配置文件中进行修改,所谓的IOC,一句话搞定:对象由Spring来创建,管理,装配!
总结:在配置文件加载的时候,容器中管理的所有对象已经被初始化了!
这个import,一般用于团队开发使用,他可以将多个配置文件,导入合并为一个!
假设,现在项目中有多个人开发,这三个人复制不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
使用的时候,直接使用总的配置就可以了!
import com.panghl.pojo.User;
import com.panghl.pojo.UserT;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/16 21:31
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
//Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserT hello = (UserT) context.getBean("userT2");
hello.show();
System.out.println(hello.getName());
}
}
4.2已经说过了!
1、复杂类型
package com.panghl.pojo;
/**
* @Author panghl
* @Date 2021/3/16 22:30
* @Description TODO
**/
public class Address {
private String adress;
public String getAdress() {
return adress;
}
public void setAdress(String adress) {
this.adress = adress;
}
}
2、真实测试对象
package com.panghl.pojo;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
/**
* @Author panghl
* @Date 2021/3/16 22:30
* @Description TODO
**/
public class Student {
private String name;
private Address address;
private String[] books;
private List hobbys;
private Map card;
private Set games;
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 getGames() {
return games;
}
public void setGames(Set games) {
this.games = games;
}
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;
}
}
3、beans.xml
红楼梦
西游记
水浒传
三国演义
听课
看电影
敲代码
Lol
cs
BOB
174061000
pangh1000
男
4、测试类
import com.panghl.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/16 21:31
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
//Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
Student student = (Student)context.getBean("student");
System.out.println(student.toString());
}
}
我们可以使用p命令和c命令进行注入
官方解释:
使用:
测试:
import com.panghl.pojo.Student;
import com.panghl.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/16 21:31
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
//Spring容器
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml","userbeans.xml");
Student student = (Student)context.getBean("student");
System.out.println(student.toString());
User user = (User)context.getBean("user");
System.out.println(user.getName());
User user2 = (User)context.getBean("user2");
System.out.println(user2.getName());
}
}
3、其余的request、session、application、这些个只能在web开发中使用到!
在Spring中有三种装配方式
环境搭建:一个人有两个宠物!
jdk1.5支持的注解!Spring2.5就支持注解!
基于注解的配置的引入提出了一个问题,即这种方法是否比 XML“更好”。简短的答案是“取决于情况”。
@Nullable 字段标记了这个注解,说明这个字段可以为null
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
/**
* Declares whether the annotated dependency is required.
* Defaults to {@code true}.
*/
boolean required() default true;
}
//如果显示定义了AutoWired的required属性为false,说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
public class People {
@Resource(name = "cata")
private Cat cat;
@Autowired
@Qualifier(value = "dog2222")
private Dog dog;
private String name;
}
小结:
@Resource和@Autowired的区别:
在Spring4之后,要使用注解开发,必须要保证aop的包导入了
//等价于
//@Component 组件
@Component
public class User {
public String name = "panghl";
}
@Component
public class User {
public String name;
//相当于
@Value("panghl2")
public void setName(String name) {
this.name = name;
}
}
@Component 有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
@Scope("prototype")
xml与注解最佳实践:
package com.kuang.pojo;
import org.springframework.stereotype.Component;
/**
* @Author panghl
* @Date 2021/3/18 22:24
* @Description TODO
**/
//这里这个注解的意思,就是说明这个类被Spring接管了,注册到了容器中
@Component
public class User {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
配置类:
package com.kuang.config;
import com.kuang.pojo.User;
import org.springframework.context.annotation.*;
/**
* @Author panghl
* @Date 2021/3/18 22:25
* @Description TODO
**/
//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component,
// @Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@ComponentScan("com.kuang.pojo")
public class ApplicationConfig2 {
//注册一个bean,就相当于我们之前写的一个bean标签
//这个方法的名字,就相当于bean标签中的id属性
//这个方法的返回值,就相当于bean标签中的class属性
@Bean
public User user(){
User user = new User();
user.setName("hello");
return user; //就是返回要注入到bean的对象
}
}
package com.kuang.config;
import com.kuang.pojo.User;
import org.springframework.context.annotation.*;
/**
* @Author panghl
* @Date 2021/3/18 22:25
* @Description TODO
**/
//这个也会Spring容器托管,注册到容器中,因为他本来就是一个@Component,
// @Configuration代表这是一个配置类,就和我们之前看的beans.xml
@Configuration
@Import(ApplicationConfig2.class)
public class ApplicationConfig {
}
测试类:
import com.kuang.config.ApplicationConfig;
import com.kuang.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
/**
* @Author panghl
* @Date 2021/3/18 22:26
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
//如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig 上下文来获取容器,通过配置类的class对象加载
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfig.class);
User user = (User)applicationContext.getBean("user");
System.out.println(user.getName());
}
}
package com.panghl.demo1;
/**
* @Author panghl
* @Date 2021/3/18 22:56
* @Version 1.0
* @Description 租房
**/
public interface Rent {
public void rent();
}
package com.panghl.demo1;
/**
* @Author panghl
* @Date 2021/3/18 22:56
* @Description 房东
**/
public class Host implements Rent{
@Override
public void rent() {
System.out.println("房东要出租");
}
}
package com.panghl.demo1;
/**
* @Author panghl
* @Date 2021/3/18 22:59
* @Description TODO
**/
public class Proxy implements Rent {
private Host host;
public Proxy(Host host) {
this.host = host;
}
public Proxy() {
}
@Override
public void rent() {
seeHouse();
host.rent();
fare();
sign();
}
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
//签合同
public void sign(){
System.out.println("中介签合同");
}
}
package com.panghl.demo1;
/**
* @Author panghl
* @Date 2021/3/18 22:58
* @Description TODO
**/
public class Client {
public static void main(String[] args) {
//房东要租房子
Host host = new Host();
//代理,中介带房东租房子,但是呢?代理角色一般会有些附属操作
Proxy proxy = new Proxy(host);
//你不用面对房东,直接找中介租房即可!
proxy.rent();
}
}
package com.panghl.demo2;
/**
* @Author panghl
* @Date 2021/3/18 23:08
* @Description TODO
**/
//接口 - 抽象角色
public interface UserService {
public void add();
public void edit();
public void delete();
public void select();
}
package com.panghl.demo2;
/**
* @Author panghl
* @Date 2021/3/18 23:08
* @Description TODO
**/
//真实对象
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加用户");
}
@Override
public void edit() {
System.out.println("修改用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void select() {
System.out.println("查询用户");
}
//改动原有的业务代码,在公司中是大忌
}
package com.panghl.demo2;
/**
* @Author panghl
* @Date 2021/3/18 23:10
* @Description TODO
**/
public class UserServiceProxy implements UserService {
private UserServiceImpl userService;
public void setUserService(UserServiceImpl userService) {
this.userService = userService;
}
@Override
public void add() {
log("add");
userService.add();
}
@Override
public void edit() {
log("edit");
userService.edit();
}
@Override
public void delete() {
log("delete");
userService.delete();
}
@Override
public void select() {
log("select");
userService.select();
}
public void log(String msg){
System.out.println("打印了日志--使用了"+msg+"方法");
}
}
package com.panghl.demo2;
/**
* @Author panghl
* @Date 2021/3/18 23:09
* @Description TODO
**/
public class Client {
public static void main(String[] args) {
UserServiceImpl userService =new UserServiceImpl();
UserServiceProxy proxy = new UserServiceProxy();
proxy.setUserService(userService);
proxy.add();
proxy.edit();
proxy.delete();
proxy.select();
}
}
聊聊AOP:
package com.panghl.demo03;
/**
* @Author panghl
* @Date 2021/3/18 22:56
* @Version 1.0
* @Description 租房
**/
public interface Rent {
public void rent();
}
真实角色:
package com.panghl.demo03;
/**
* @Author panghl
* @Date 2021/3/18 22:56
* @Description 房东
**/
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房东要出租");
}
}
自动生成代理类!
package com.panghl.demo03;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author panghl
* @Date 2021/3/20 11:15
* @Description TODO
**/
//自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {
//被代理的接口
private Rent rent;
public void setRent(Rent rent) {
this.rent = rent;
}
//生成得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理实例,并返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
//动态代理的本质,就是使用反射机制实现
Object result = method.invoke(rent, args);
fare();
return result;
}
public void seeHouse(){
System.out.println("中介看房了");
}
public void fare(){
System.out.println("收中介费");
}
}
AOP(Aspect Oriented Programming) 意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的同一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,就是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
提供声明式事务;允许用户自定义切面
org.aspectj
aspectjweaver
1.9.4
package com.panghl.service;
/**
* @Author panghl
* @Date 2021/3/18 23:08
* @Description TODO
**/
//接口 - 抽象角色
public interface UserService {
public int add();
public int edit();
public int delete();
public int select();
}
package com.panghl.service;
/**
* @Author panghl
* @Date 2021/3/18 23:08
* @Description TODO
**/
//真实对象
public class UserServiceImpl implements UserService{
@Override
public int add() {
System.out.println("增加用户");
return 1;
}
@Override
public int edit() {
System.out.println("修改用户");
return 1;
}
@Override
public int delete() {
System.out.println("删除用户");
return 1;
}
@Override
public int select() {
System.out.println("查询用户");
return 1;
}
//改动原有的业务代码,在公司中是大忌
}
package com.panghl.log;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
/**
* @Author panghl
* @Date 2021/3/20 11:57
* @Description TODO
**/
public class Log implements MethodBeforeAdvice {
//method: 要执行的目标对象的方法
//args:参数
//target:目标对象
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println(target.getClass().getName()+"的"+method.getName()+"被执行了");
}
}
package com.panghl.log;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;
/**
* @Author panghl
* @Date 2021/3/20 12:04
* @Description TODO
**/
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);
}
}
import com.panghl.service.UserService;
import com.panghl.service.UserServiceImpl;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/20 12:15
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
//动态代理代理的是接口
UserService userService = (UserService)context.getBean("userService");
userService.add();
}
}
package com.panghl.diy;
/**
* @Author panghl
* @Date 2021/3/20 12:22
* @Description TODO
**/
public class DiyPointCut {
public void before(){
System.out.println("==========方法执行前=========");
}
public void after(){
System.out.println("==========方法执行后=========");
}
}
package com.panghl.diy;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
/**
* @Author panghl
* @Date 2021/3/20 14:34
* @Description 方式三:使用注解方式实现AOP
**/
@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
//切入点
@Pointcut("execution(* com.panghl.service.UserServiceImpl.*(..))")
public void pointCut(){
}
@Before("pointCut()")
public void before(){
System.out.println("方法执行前");
}
@After("pointCut()")
public void after(){
System.out.println("方法执行后");
}
//在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点;
@Around("pointCut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("环绕前。。。");
//获得签名
System.out.println("signature->:"+joinPoint.getSignature());
System.out.println("signature->:"+joinPoint.getSignature().getName());
//执行方法
Object proceed = joinPoint.proceed();
System.out.println("环绕后...");
System.out.println(proceed);
return proceed;
}
}
1、导入相关jar包
2、编写配置文件
3、测试
package com.panghl.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author panghl
* @Date 2021/3/20 15:29
* @Description TODO
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
spring-study
com.panghl
1.0-SNAPSHOT
4.0.0
spring-10-mybatis
junit
junit
4.12
mysql
mysql-connector-java
8.0.21
org.mybatis
mybatis
3.5.2
org.mybatis
mybatis-spring
2.0.2
org.springframework
spring-webmvc
5.1.9.RELEASE
org.springframework
spring-jdbc
5.1.9.RELEASE
org.aspectj
aspectjweaver
1.9.4
org.projectlombok
lombok
1.16.10
src/main/resources
**/*.properties
**/*.xml
false
src/main/java
**/*.properties
**/*.xml
true
package com.panghl.mapper;
import com.panghl.pojo.User;
import java.util.List;
/**
* @Author panghl
* @Date 2021/3/20 15:32
* @Version 1.0
* @Description TODO
**/
public interface UserMapper {
public List selectUsers();
}
官网:http://mybatis.org/spring/zh/index.html
MyBatis-Spring 会帮助你将 MyBatis 代码无缝地整合到 Spring 中。它将允许 MyBatis 参与到 Spring 的事务管理之中,创建映射器 mapper 和 SqlSession
并注入到 bean 中,以及将 Mybatis 的异常转换为 Spring 的 DataAccessException
。 最终,可以做到应用代码不依赖于 MyBatis,Spring 或 MyBatis-Spring。
Spring 2.0 只支持 iBatis 2.0。那么,我们就想将 MyBatis3 的支持添加到 Spring 3.0 中(参见 Spring Jira 中的 问题 )。不幸的是,Spring 3.0 的开发在 MyBatis 3.0 官方发布前就结束了。 由于 Spring 开发团队不想发布一个基于未发布版的 MyBatis 的整合支持,如果要获得 Spring 官方的支持,只能等待下一次的发布了。基于在 Spring 中对 MyBatis 提供支持的兴趣,MyBatis 社区认为,应该开始召集有兴趣参与其中的贡献者们,将对 Spring 的集成作为 MyBatis 的一个社区子项目。
1、编写数据源配置
2、SqlSessionFactory
3、sqlSessionTemplate
4、需要给接口加实现类【】
5、将字节写的实现类,注入到Spring中
6、测试使用即可!
@Test
public void springMybatis(){
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapperImpl userMapperIml = (UserMapperImpl)context.getBean("userMapperImpl");
System.out.println(userMapperIml.selectUsers());
}
SqlSessionDaoSupport
是一个抽象的支持类,用来为你提供 SqlSession
。调用 getSqlSession()
方法你会得到一个 SqlSessionTemplate
,之后可以用于执行 SQL 方法!
package com.panghl.mapper;
import com.panghl.pojo.User;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
/**
* @Author panghl
* @Date 2021/3/20 16:33
* @Description TODO
**/
public class UserMapperImpl2 extends SqlSessionDaoSupport implements UserMapper{
@Override
public List selectUsers() {
SqlSession sqlSession = getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
return mapper.selectUsers();
}
}
事务ACID原则:
声明式事务:AOP
编程式事务:需要在代码中进行事务的管理
实体类:
package com.panghl.domain;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
private int id;
private String name;
private String pwd;
}
UserMapper:
package com.panghl.mapper;
import com.panghl.domain.User;
import java.util.List;
/**
* @Author panghl
* @Date 2021/3/20 15:32
* @Version 1.0
* @Description TODO
**/
public interface UserMapper {
public List selectUser();
public void insert(User user);
public void deleteById(int id);
}
insert into user (id,name,pwd) value(#{id},#{name},#{pwd})
deletes from user where id=#{id}
package com.panghl.mapper;
import com.panghl.domain.User;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.support.SqlSessionDaoSupport;
import java.util.List;
/**
* @Author panghl
* @Date 2021/3/20 18:29
* @Description TODO
**/
public class UserMapperImpl3 extends SqlSessionDaoSupport implements UserMapper {
@Override
public List selectUser() {
User user = new User(10,"ddd","ddd");
insert(user);
deleteById(10);
return getSqlSession().getMapper(UserMapper.class).selectUser();
}
@Override
public void insert(User user) {
getSqlSession().getMapper(UserMapper.class).insert(user);
}
@Override
public void deleteById(int id) {
getSqlSession().getMapper(UserMapper.class).deleteById(id);
}
}
mybatis配置文件:
spring配置文件:
测试:
import com.panghl.mapper.UserMapper;
import com.panghl.mapper.UserMapperImpl3;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* @Author panghl
* @Date 2021/3/20 15:38
* @Description TODO
**/
public class MyTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-dao.xml");
UserMapper userMapperIml = (UserMapper)context.getBean("userDao");
System.out.println(userMapperIml.selectUser());
}
}
Spring声明式事务@Transactional 详解,事务隔离级别和传播行为 :https://blog.csdn.net/qq_45441466/article/details/115035741
思考:
为什么需要事务?