本文根据尚硅谷王老师的Spring5视频教程总结的。z作者跟着教程全程实践,本文内容较为简略,详细内容请移步王老师视频教程。
轻量级开源的JavaEE框架
核心部分:
(1)IOC:控制反转,将创建对象交给Spring管理
(2)AOP:面向切面,不修改源代码进行功能增强
IOC基本包:
控制反转:将创建对象和对象之间的调用过程交给Spring进行管理
使用目的:降低代码耦合度
xml解析、工厂模式、反射
第一步:xml配置文件,配置创建的对象(bean对象)
第二步:创建工厂类
IOC基于IOC容器完成,IOC容器底层即对象工厂
IOC容器实现:
(1)BeanFactory:加载配置文件时不会创建对象,在获取对象(使用)时才会去创建对象 (内部使用接口)
(2)ApplicationContext:加载配置文件时就会把配置文件中的对象创建 (开发人员使用)
Bean管理:
(1)创建对象
(2)注入属性
创建对象:
在配置文件中添加bean标签,标签中添加对应属性,实现对象创建
注入属性:
(1)使用set方法注入
类中创建对应属性set()方法—>配置文件中配置属性注入
/*** 演示使用set方法注入属性*/
public class Book {//创建属性private String bname;private String bauthor;private String adderss;//创建属性对应的set方法public void setBname(String bname){this.bname = bname;}public void setBauthor(String bauthor) {this.bauthor = bauthor;}public void setAddress(String address) {this.adderss = address;}public void testDemo(){System.out.println(bname+" "+bauthor+" "+adderss);}
}<!-- 2 set方法注入属性-->
<bean id="book" class="com.atguigu.spring5.Book"><!-- 使用property完成属性注入 --><property name="bname" value="易筋经"></property><property name="bauthor" value="达摩老祖"/><!-- 属性值为空 --><!--<property name="address"><null></null></property>--><!-- 属性值包含特殊字符 --><property name="address"><value><![CDATA[<<南京>>]]></value></property>
</bean>
(2)使用有参构造函数注入
类中创建对应属性有参构造方法—>配置文件中属性注入
public class Orders {//属性private String oname;private String address;//有参构造public Orders(String oname, String address) {ame = oname;this.address = address;}public void testOrders(){System.out.println(oname+" "+address);}
}<!-- 3 有参构造注入属性 -->
<bean id="orders" class="com.atguigu.spring5.Orders"><constructor-arg name="oname" value="abc"></constructor-arg><constructor-arg name="address" value="Chain"></constructor-arg>
</bean>
注入外部属性(默认set()方法注入)
类中属性为另一个类(如service中注入dao)
创建两个类service和dao—>seivice中属性为dao—>为dao创建set()方法—>配置类中创建service和dao对象—>在service的bean对象中注入dao对象
public class UserService {//创建UserDao类型属性,生成set方法private UserDao userDao;public void setUserDao(UserDao userDao){this.userDao = userDao;}public void add(){System.out.println("");userDao.update();//原始方式//UserDao userDao = new UserDaoImpl();//userDao.update();}
}<!-- 1 service和dao对象创建 -->
<bean id="userService" class="com.atguigu.spring5.service.UserService"><!--2 注入UserDao对象name属性:类里面属性名称ref属性:创建userDao对象bean标签id值--><property name="userDao" ref="userDaoImpl"></property>
</bean>
<bean id="userDaoImpl" class="com.atguigu.spring5.dao.UserDaoImpl"></bean>
注入内部属性(默认set()方法注入)
<!-- 内部bean -->
<bean id="emp" class="com.atguigu.spring5.bean.Emp"><!-- 先设置两个普通的属性 --><property name="ename" value="lucy"></property><property name="gender" value="女"></property><!-- 设置对象类型属性 --><property name="dept"><bean id="dept" class="com.atguigu.spring5.bean.Dept"><property name="dname" value="安保部"></property></bean></property>
</bean>
注入集合属性(默认set()方法注入)
创建类,定义数组、list、map、set类型属性,生成set()方法—>在配置文件中进行配置
<!-- 集合类型属性注入 -->
<bean id="stu" class="com.atgui<!-- 数组类型属性注入 --><property name="course"><array><value>java课程</valu<value>数据库课程</value</array></property><!-- list类型属性注入 --><property name="list"><list><value>张三</value><value>小三</value></list></property><!-- map类型属性注入 --><property name="maps"><map><entry key="JAVA" v<entry key="PHP" va</map></property><!-- set类型属性注入 --><property name="set"><set><value>MySQL</value<value>Redis</value</set></property><!-- 注入List集合类型,值是对象 --><property name="courseList"<list><ref bean="course1"<ref bean="course2"</list></property>
</bean><!-- 创建多个course对象 -->
<bean id="course1" class="com.llectiontype.Course"><property name="cname" value="Spring5框架"></property>
</bean>
<bean id="course2" class="com.llectiontype.Course"><property name="cname" value="MyBatis框架"></property>
</bean>
注解格式:@注解名称(属性名称=属性值,属性名称=属性值…)
使用目的:简化xml配置
Bean管理注解:@Controller、@Service、@Repository、@Component
创建对象:
引入依赖—>开启组件扫描—>在类上面添加注解—>组件扫描细节
<!-- 开启组件扫描 1 如果扫描多个包,使用逗号隔开2 扫描包上层目录-->
<context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan>
//在注解里面value可以省略不写,默认是类名称首字母小写 UserService->userService
//@Component(value = "userService") //类似于xml文件中定义<bean id="userService" class=".."/>
@Service
//@Controller
//@Repository
public class UserService {}
属性注入:
@Autowired:根据属性类型进行自动装配
@Qualifier:根据名称进行注入
@Resource:根据属性类型或者名称进行注入
@Value:注入普通类型属性
创建service和dao对象—>在service和dao上添加注解—>开启组件扫描
在service中添加dao属性—>在属性上使用注入注解
创建配置类代替xml配置文件
@Configuration //作为配置类,替代xml配置文件
@ComponentScan(basePackages = {"com.atguigu"})
public class SpringConfig { }
普通bean:配置文件中定义的bean类型就是返回类型
工厂Bean:配置文件中定义的bean类型和返回类型不一样
(1)创建类,让其作为工厂类,实现接口FactoryBean
(2)实现接口里面的方法,在实现的方法中定义返回的bean类型
默认情况下,bean是单实例对象—意思是创建的多个实例对象,其指向的地址是一个
设置多实例对象—只需在配置文件bean标签中设置scope属性为prototype
区别:
单实例在加载配置文件时就会创建单实例对象
多实例在调用getBean方法是创建多实例对象
(1)配置数据库信息
配置德鲁伊连接池—>引入德鲁伊的依赖jar包
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close"><property name="url" value="jdbc:mysql://localhost:3306/userDb" /><property name="driverClassName" value=sql.jdbc.Driver" /><property name="username" value="root" /><property name="password" value="123" />
</bean>
(2)引入外部properties属性文件到配置文件中
引入conetxt名称空间—>配置文件中使用标签引入外部属性文件
<!-- 引入外部属性文件 -->
<context:property-placeholder location="classpath:jdbc.properties"></context:property-placeholder>
<!-- 配置连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"><property name="driverClassName" value="${prop.driverClass}"></property><property name="url" value="${prop.url}"></property><property name="username" value="${prop.username}"></property><property name="password" value="${prop.password}"></property>
</bean>
面向切面编程,可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低。即:通过不修改源代码的方式,在主干功能里边添加新功能
使用动态代理
(1)有接口,使用JDK动态代理
创建接口实现类代理对象,增强类的方法
(2)无接口,使用CGLIB动态代理
创建当前类子类的代理对象,增强类的方法
(1)使用Proxy类中的方法创建代理对象
方法中的三个参数分别是类加载器、增强方法所在的类、实现这个接口的InvocationHandler
(2)编写JDK动态代理代码
创建接口,定义方法—>创建接口实现类,实现方法—>使用Proxy类创建接口代理对象—>创建代理对象代码
// 创建接口实现类代理对象
public class JDKProxy { public static void main(String[] args) { Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); UserDao dao = (UserDao)Proxy. newProxyInstance (ClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1, 2);System. out .println("result:"+result); }
}
// 创建代理对象代码
class UserDaoProxy implements InvocationHandler { //1 把创建的是谁的代理对象,把谁传递过来 // 有参数构造传递 private Object obj; public UserDaoProxy(Object obj) { this.obj = obj; } // 增强的逻辑 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 方法之前 System. out .println("方法之前执行...."Name()+" :传递的参 数..."+ Arrays. toString (args)); // 被增强的方法执行 Object res = method.invoke(obj, args); // 方法之后 System. out .println("方法之后执行...."+obj); return res; }
}
连接点:类里面哪些方法可以被增强,这些方法称为连接点
切入点:实际被增强的方法
通知(增强):实际增强的逻辑部分 (分类为前置、后置、环绕、异常、最终通知)
切面:把通知应用到切入点的过程
一般地,通过AspectJ和Spring框架一起使用进行AOP操作
基于AspectJ实现方式:xml和注解
引入AOP相关依赖
切入点表达式:知道对哪个类的哪个方法进行增强: execution(* [返回类型] [类全路径] 方法名称 ) :例:execution(* com.atguigu.dao.BookDao.add(…))
—>创建类,在类里面定义方法
—>创建增强类(编写增强逻辑)
—>进行通知的配置
开启注解扫描->@Component注解上面创建的类->在增强类上添加注解@Aspect->开启Aspect生成代理对象
<!-- 开启 Aspect 生成代理对象 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
—>配置不同类型的通知
在增强类的里面,在作为通知方法上面添加通知类型注解,使用切入点表达式配置
@Before(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
—>相同的切入点的抽取
@Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))")
—>有多个增强类对同一方法进行增强,设置增强类优先级
增强类上面添加注解 @Order(数字类型值),数字类型值越小优先级越高
—>完全使用注解开发
@Configuration
@ComponentScan(basePackages = {"com.atguigu"}) @EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop { }
Spring框架对JDBC进行封装,使用JdbcTemplate实现对数据库的操作
—>引入相关jar包
—>配置文件中配置组件扫描和数据库连接池dataSource
—>配置JdbcTemplate对象,注入dataSource
—>创建service类和dao类,在dao中注入jdbcTemplate对象
//添加数据
//1 创建 sql 语句
String sql = "insert into t_book values(?,?,?)";
//2 调用方法实现
Object[] args = {UserId(), Username(), Ustatus()};
int update = jdbcTemplate.update(sql,args); //修改数据
String sql = "update t_book set username=?,ustatus=? where user_id=?";
Object[] args = {Username(), Ustatus(),UserId()};
int update = jdbcTemplate.update(sql, args); //删除数据String sql = "delete from t_book where user_id=?";
int update = jdbcTemplate.update(sql, id); //查询表记录
String sql = "select count ( * ) from t_book";
Integer count = jdbcTemplate.queryForObject(sql, Integer.class);//查询返回对象
String sql = "select * from t_book where user_id=?";
Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<Book>(Book.class), id); //查询返回集合
String sql = "select * from t_book";
List<Book> bookList = jdbcTemplate.query(sql, new BeanPropertyRowMapper<Book>(Book.class));//批量添加
public void batchAddBook(List<Object[]> batchArgs) { String sql = "insert into t_book values(?,?,?)"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);System.out.String(ints));
}
//批量添加测试
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3","java","a"};
Object[] o2 = {"4","c++","b"};
Object[] o3 = {"5","MySQL","c"};
batchArgs.add(o1); batchArgs.add(o2); batchArgs.add(o3);
bookService.batchAdd(batchArgs); //批量修改
public void batchUpdateBook(List<Object[]> batchArgs) { String sql = "update t_book set username=?,ustatus=? where user_id=?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System. out .println(Arrays. toString (ints));
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"java0909","a3","3"};
Object[] o2 = {"c++1010","b4","4"};
Object[] o3 = {"MySQL1111","c5","5"};
batchArgs.add(o1); batchArgs.add(o2); batchArgs.add(o3);
bookService.batchUpdate(batchArgs);//批量删除
public void batchDeleteBook(List<Object[]> batchArgs) { String sql = "delete from t_book where user_id=?"; int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs); System. out .println(Arrays. toString (ints));
}
List<Object[]> batchArgs = new ArrayList<>();
Object[] o1 = {"3"}; Object[] o2 = {"4"};
batchArgs.add(o1); batchArgs.add(o2);
bookService.batchDelete(batchArgs);
事务是数据库操作最基本单元,逻辑上一组操作,要么都成功,如果有一个失败所有操作都失败
特性(ACID):原子性、一致性、隔离性、持久性
—>配置文件中配置事务管理器并引入名称空间tx
<! -- 创建事务管理器 -- >
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"></property>
</bean>
—>开启事务注解
<! -- 开启事务注解 -- >
<tx:annotation-driven transactionmanager="transactionManager"></tx:annotation-driven>
—>在所需的类或方法上添加事务注解@Transactional
—>事务管理参数配置
propagation:事务传播行为
ioslation:事务隔离级别,多事务操作之间不会产生影响,解决:脏读、不可重复读、虚(幻)读
timeout:超时时间
readOnly:是否只读
rollbackFor:回滚
noRollbackFor:不回滚
@Configuration // 配置类
@ComponentScan(basePackages = "com.atguigu") // 组件扫描
@EnableTransactionManagement // 开启事务
public class TxConfig { // 创建数据库连接池 @Bean public DruidDataSource getDruidDataSource() { DruidDataSource dataSource = new DruidDataSource();dataSource.setDriverClassName(sql.jdbc.Driver");dataSource.setUrl("jdbc:mysql:///user_db"); dataSource.setUsername("root"); dataSource.setPassword("root"); return dataSource; } // 创建 JdbcTemplate 对象 @Bean public JdbcTemplate getJdbcTemplate(DataSource dataSource) { // 到 ioc 容器中根据类型找到 dataSource JdbcTemplate jdbcTemplate = new JdbcTemplate(); // 注入 dataSource jdbcTemplate.setDataSource(dataSource); return jdbcTemplate; } // 创建事务管理器 @Bean public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();transactionManager.setDataSource(dataSource); return transactionManager; }
}
引入jar包—>创建 l配置文件
<? xml version="1.0" encoding="UTF-8" ?>
<! -- 日志级别以及优先级排序 : OFF > FATAL > ERROR > WARN > INFO > DEBUG > TRACE > ALL -- >
<! -- Configuration 后面的 status 用于设置 log4j2 自身内部的信息输出,可以不设置, 当设置成 trace 时,可以看到 log4j2 内部各种详细输出 -- >
<configuration status="INFO"> <! -- 先定义所有的 appender -- > <appenders> <! -- 输出日志信息到控制台 -- > <console name="Console" target="SYSTEM_OUT"> <! -- 控制日志输出的格式 -- > <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %5level %logger{36} - %msg%n"/> </console> </appenders> <! -- 然后定义 logger ,只有定义 logger 并引入的 appender , appender 才会生效 -- > <! -- root :用于指定项目的根日志,如果没有单独指定 Logger ,则会使用 root 作为 默认的日志输出 -- > <loggers> <root level="info"> <appender-ref ref="Console"/> </root></loggers>
</configuration>
@Nullable 注解可以使用在方法上面,属性上面,参数上面,表示方法返回可以为空,属性值可以为空,参数值可以为空
引入测试依赖jar包—>使用注解创建测试类
@RunWith(SpringJUnit4ClassRunner.class) // 单元测试框架
@ContextConfiguration("l") // 加载配置文件
//使用一个复合注解替代上面两个注解
//@SpringJUnitConfig(locations = "l")
public class JTest4 {@Autowiredprivate UserService userService;@Testpublic void test1() {userService.accountMoney();}
}
以上是JUnit4,使用JUnit5只需在导入@Test换成5的即可
Spring5 添加新的模块,用于 web 开发的,功能和 SpringMVC 类似的,Webflux 使用 当前一种比较流程响应式编程出现的框架
使用传统 web 框架,比如 SpringMVC,这些基于 Servlet 容器,Webflux 是一种异步非阻 塞的框架,异步非阻塞的框架在 Servlet3.1 以后才支持,核心是基于 Reactor 的相关 API 实现的
异步和同步针对调用者,调用者发送请求,如果等着对方回应之后才去做其他事情就是同 步,如果发送请求之后不等着对方回应就去做其他事情就是异步
阻塞和非阻塞针对被调用者,被调用者受到请求之后,做完请求任务之后才给出反馈就是阻 塞,受到请求之后马上给出反馈然后再去做事情就是非阻塞
实例:
第一步 创建 SpringBoot 工程,引入 Webflux 依赖
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
第二步 配置启动端口号
server.port=8081
第三步 创建包和相关类
//实体类
public class User {private String name;private String gender;private Integer age;public User(String name, String gender, Integer age) {this.name = der = gender;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getGender() {return gender;}public void setGender(String gender) {der = gender;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}
}//用户操作接口
public interface UserService {//根据ID查询用户Mono<User> getUserById(int id);//查询所有用户Flux<User> getAllUser();//添加用户Mono<Void> saveUserInfo(Mono<User> user);
}@Repository
public class UserServiceImpl implements UserService {//创建Map集合存储数据private final Map<Integer,User> users = new HashMap<>();public UserServiceImpl(){this.users.put(1,new User("lucy","nan",20));this.users.put(2,new User("mary","nv",30));this.users.put(3,new User("jack","nv",50));}//根据ID查询@Overridepublic Mono<User> getUserById(int id) {return Mono.justOrEmpty((id));}//查询多个用户@Overridepublic Flux<User> getAllUser() {return Flux.fromIterable(this.users.values());//取出集合}//添加@Overridepublic Mono<Void> saveUserInfo(Mono<User> userMono) {return userMono.doOnNext(person ->{ //uesrMono中的值放到person中//向Map集合中放值int id = users.size()+1;users.put(id,person);}).pty());//清空里边的值}
}@RestController
public class UserController {@Autowiredprivate UserService userService;//id查询@GetMapping("/user/{id}")public Mono<User> getUserId(@PathVariable int id){UserById(id);}//查询所有@GetMapping("/user")public Flux<User> getUsers(){AllUser();}//添加@PostMapping("/saveuser")public Mono<Void> saveUser(@RequestBody User user){Mono<User> userMono = Mono.just(user);return userService.saveUserInfo(userMono);}
}
本文发布于:2024-01-29 01:59:33,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170646477811909.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |