栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring5框架 笔记总结(二)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring5框架 笔记总结(二)

文章目录
  • 1. 使用Java 的方式配置Spring
  • 2. 代理模式
  • 3. 动态代理 简述
  • 4. 动态代理的使用
  • 5. Spring AOP
  • 6. 实现aop(一) 通过SpringAPI接口实现(围绕接口来实现)
  • 7. execution()方法参数含义
  • 8. 实现aop(二) 自定义类方式 (围绕自定义类,也就是切面(aspect)定义来实现)
  • 9. 实现aop(三) 使用注解来实现
  • 10. JDBC Template 概述 和 准备
  • 11. JDBC Template 的增删改查
  • 12. JdbcTemplate 的批量操作

1. 使用Java 的方式配置Spring

我们不完全使用Spring的xml来配置,我们使用Java代码的方式来操作。

JavaConfig是Spring的一个子项目,在Spring 4之后,他成为了一个核心功能!


通过 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 来获取容器context,对应的情况不同!

前者是通过Spring和xml方式来获取的,后者是通过部分Spring注解和Java代码获取的!

代码如下:

User.java代码(实体类):

package com.itholmes.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

//此时@Component注解的意思,就是说明这个类被Spring接管了,注册到容器中。
@Component
public class User {

    private String name;

    public String getName() {
        return name;
    }

    @Value("itholmes")//属性注入值,也可以在set方法上面。
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + ''' +
                '}';
    }
}

config层下的HolmesConfig.java配置类:

一定记住配置类中几个注解的使用!

package com.itholmes.config;

import com.itholmes.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.import;

//@Configuration注解也会被Spring容器托管,注册到容器中,因为它本身也包含了@Component注解。
//@Configuration代表这是一个配置类,就和我们之前的beans.xml文件是一样的。
@Configuration
@ComponentScan("com.itholmes.pojo")//同样也可以通过@ComponentScan,在这里进行一个扫描操作。
@import(HolmesConfig2.class)//@import注解,将相应的配置文件导入当前,也就是合并的效果。
public class HolmesConfig {

    //注册一个bean,就相当于我们之前写的一个bean标签。
    //该方法的名字getUser就是相当于bean标签中的id属性。
    //这个方法的返回值,就相当于bean标签中的class属性。
    @Bean
    public User getUser(){
        return new User();//就是返回值,要注入到bean中的对象。
    }

}

模拟导入HolmesConifg配置类的配置类2:

package com.itholmes.config;

import org.springframework.context.annotation.Configuration;

@Configuration
public class HolmesConfig2 {

}

测试类:

一定牢记测试类中的AnnotationConfigApplicationContext(HolmesConfig.class);作用!


import com.itholmes.config.HolmesConfig;
import com.itholmes.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class MyTest {

    public static void main(String[] args) {
        //如果完全使用了配置类方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载。
        ApplicationContext context = new AnnotationConfigApplicationContext(HolmesConfig.class);
        User user = context.getBean("getUser", User.class);
        System.out.println(user.getName());
    }

}

这种纯java的配置方式,在Spring Boot中随处可见。

2. 代理模式

Java的23种设计模式之一的代理模式,很重要,因为它是Spring SOP的底层内容。

代理模式的分类:

  • 静态代理。
  • 动态代理。

平时,我们学习中操作的都是静态代理模式,定义一个接口,一个用户,一个代理角色,一个厂家。用户通过代理来获取操作厂家提供资源的一个效果。


纵向开发 和 横向开发的效果图:

3. 动态代理 简述

简而言之,动态代理,在代理模式的情况下,它是自动生成代理类。

动态代理的描述:

  • 动态代理的底层都是通过反射来实现的。
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理。
    • 基于接口动态代理机制:JDK动态代理(也是默认的)。
    • 基于类的动态代理机制:cglib动态代理。
    • java字节码实现:Javassist。

Spring AOP是基于动态代理的,基于两种动态代理机制:JDK动态代理(也是默认的)和CGLIB动态代理。


需要了解两个类:Proxy (代理),InvocationHandler (调用处理程序)。

InvocationHandler是java.lang.reflect反射包下的一个接口:

Proxy 是java.lang.reflect反射包下的一个类:

proxy类对应的4个静态方法:

4. 动态代理的使用

Rent接口:

package com.itholmes.demo3;

public interface Rent {
    void rent();
}

Host类(房东):

package com.itholmes.demo3;

public class Host implements Rent{

    @Override
    public void rent() {
        System.out.println("房东要出租房子!");
    }

}

ProxyInvocationHandler.java实现InvocationHandler接口的类,这个类可以自动生成代理类。

package com.itholmes.demo3;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//我们会用这个类自动生成代理类!
public class ProxyInvocationHandler implements InvocationHandler {

    //被代理的接口
    private Rent rent;

    public void setRent(Rent rent) {
        this.rent = rent;
    }

    //生成得到代理类
    //第一个参数,类构造器:this.getClass().getClassLoader()加载到代理类在那个位置。
    //第二个参数,得到实现rent的接口:rent.getClass().getInterfaces()表示它要代理的接口是哪一个接口。
    //第三个参数,实现InvocationHandler的类,这里我们本身就实现了InvocationHandler了,所以用this就可,。
    public Object getProxy(){
        Object o = Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);
        //System.out.println("判断o:"+o);
        return o;
    }

    //上面的Proxy.newProxyInstance()方法执行后,会执行当前的invoke方法来处理代理实例,并返回结果。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        seeHouse();

        //动态代理的本质,就是使用反射机制实现的!
        Object invoke = method.invoke(rent, args);
        //System.out.println("判断invoke:"+invoke);

        fare();

        return invoke;
    }

    //我们可以通过打印来判断这里的invoke对象和上面的o对象是一个对象么?
    //invoke:com.itholmes.demo3.Host@2b193f2d
    //getProxy:com.itholmes.demo3.Host@2b193f2d
    //返回结果不难看出就是一个对象。

    public void seeHouse(){
        System.out.println("中介带看房子");
    }

    public void fare(){
        System.out.println("中介收费");
    }
}

Client用户测试类:

package com.itholmes.demo3;

public class Client {

    public static void main(String[] args) {
        //真实角色(房主)
        Host host = new Host();

        //代理角色(中介):现在没有
        ProxyInvocationHandler handler = new ProxyInvocationHandler();
        //通过调用程序处理角色(当前我们定义的ProxyInvocationHandler类)来处理我们要调用的接口对象。
        handler.setRent(host);
        Rent proxy = (Rent)handler.getProxy();//这里的proxy就是动态生成的!
        proxy.rent();
        
    }

}

此外,invoke中的method方法可以调用很多方法,例如:
method.getName()获取名字等等。

5. Spring AOP

面向对象程序设计(Object Oriented Programming , OOP)

面向切面编程:(Aspect Oriented Programming , AOP)

AOP是OOP的延续。


AOP的一个效果图如下:


SpringAOP中,通过Advice定义横切逻辑。

在Spring中支持5种类型的Advice:

6. 实现aop(一) 通过SpringAPI接口实现(围绕接口来实现)

实现AOP前,需要一个织入依赖包aspectjweaver!

导入完包后,要导入响应的约束和支持约束条件:

其实不管什么约束条件都是差不多的格式,稍微改改字母就能修改。

xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
            http://www.springframework.org/schema/aop
            https://www.springframework.org/schema/aop/spring-aop.xsd"

上面准备工作完成后,我们创建两个类分别实现了AfterReturningAdvice 和 MethodBeforeAdvice接口:

log类实现MethodBeforeAdvice方法执行前调用它:

package com.itholmes.log;

import org.springframework.aop.MethodBeforeAdvice;

import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice{

    //before方法的参数:
    //method:要执行的目标对象的方法
    //objects:参数
    //o:目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}

AfterLog类,调用AfterReturningAdvice接口,负责执行方法执行后的内容:

package com.itholmes.log;

import org.springframework.aop.AfterReturningAdvice;

import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {

    //returnValue:使用AfterReturningAdvice是可以拿到一个returnValue返回值的。
    //其他的参数和BeforeAdvice中的before参数一样。
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] objects, Object o1) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回结构为:"+returnValue);
    }
}

UserService接口:

package com.itholmes.service;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void select();
}

UserServiceImpl实现类:

package com.itholmes.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 select() {
        System.out.println("查询了一个用户");
    }
}

再往后,先在xml文件中,注册bean,然后通过xml方式来指定aop的相关内容了。
创建applicationContext.xml文件:




    
    
    
    

    
    
    
    

        
        
        

        
        
        

    


最后,我们测试一下mytest类:

import com.itholmes.service.UserService;
import com.itholmes.service.UserServiceImpl;
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");
        //注意:AOP实现原理是动态代理,而动态代理代理的是接口,因此在这我们只能写接口类型。
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}
7. execution()方法参数含义

先说一下execution()方法参数的含义。

execution()是最常用的切点函数,其语法如下所示:

整个表达式可以分为五个部分:

  1. execution(): 表达式主体。
  2. 第一个*号:表示返回类型,*号表示所有的类型。
  3. 包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,com.sample.service.impl包、子孙包下所有类的方法。
  4. 第二个*号:表示类名,*号表示所有的类。
  5. *(..):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,两个句点表示任何参数。

这些参数理解了才更容易理解AOP。

8. 实现aop(二) 自定义类方式 (围绕自定义类,也就是切面(aspect)定义来实现)

测试类,接口,接口实现类不变。

首先,创建一个自定义类:

package com.itholmes.diy;

public class DiyPointCut {

    public void before(){
        System.out.println("------方法执行前-------");
    }

    public void after(){
        System.out.println("-------方法执行后--------");
    }

}

xml配置文件来进行配置:
其实就是换了aop:aspect来操作而已:




    
    
    
    

    
    
    

        
        

            
            

            
            
            

        
    


9. 实现aop(三) 使用注解来实现

接口,实现类,测试类不变。

设置application.xml的内容:




    
    
    
    

    
    
    
    
    


定义一个AnnotationPointCut,在里面设置注解信息。

package com.itholmes.diy;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

//方式三:使用注解来实现AOP方式

//标注:这个类是一个切面
@Aspect
public class AnnotationPointCut {

    //这里要注意一下,在junit中也有一个@Before注解,不要导错了。
    @Before("execution(* com.itholmes.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("--------方法执行前");
    }

    //同样不要到错包。
    @After("execution(* com.itholmes.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("--------方法执行后");
    }

    //在环绕增强中,我们可以给定一个参数,代表我们要获取处理切入的点。
    //joinPoint就是效果图中的连接点
    @Around("execution(* com.itholmes.service.UserServiceImpl.*(..))")
    public void around(ProceedingJoinPoint joinPoint) throws Throwable {
        System.out.println("环绕前");

        Signature signature = joinPoint.getSignature();//获得签名
        //System.out.println("signature:"+signature);

        //执行方法
        Object proceed = joinPoint.proceed();

        System.out.println("环绕后");

    }

    //注意这个执行顺序,执行谁后执行谁!
    //环绕前
    //--------方法执行前
    //增加了一个用户
    //环绕后
    //--------方法执行后

}

三种实现AOP效果都一样,后两者简便一些。

10. JDBC Template 概述 和 准备

Spring整体效果图如下,而JDBC Template是属于蓝色部分的内容:

Spring框架对JDBC进行了封装,使用JdbcTemplate方便实现对数据库操作。


第一步,导入jar包:

首先,引入jar包:(该用maven依赖的依赖,不会maven该导包的导包。)



    4.0.0

    org.example
    spring5_atguigu_demo05
    1.0-SNAPSHOT

    
        8
        8
    

    
        
        
            org.springframework
            spring-webmvc
            5.3.13
        
        
        
            mysql
            mysql-connector-java
            8.0.22
        
        
        
            com.alibaba
            druid
            1.1.9
        
        
        
            org.springframework
            spring-jdbc
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-tx
            5.2.6.RELEASE
        
        
        
            org.springframework
            spring-orm
            5.2.6.RELEASE
        

    


第二步,在Spring中配置文件,配置数据库连接池:

配置数据库连接池,传递参数。




    
    

    
    
    
        
        
        
        
     



第三步,创建对应jdbcTemplate的对象,将dataSource(第二步,配置的信息)注入里面:



    
    

    
    
    
        
        
        
        
     


    
    
        
        
    

    


第四步,创建service类,创建dao类,在dao注入jdbcTemplate对象(算是实操):

在beans.xml配置文件中添加组件扫描:


测试类Test:


import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class TestBook {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");

        BookService service = context.getBean("bookService", BookService.class);

        Book book = new Book();
        book.setBook_name("张三");
        book.setBook_password("zhangsan");

        service.addBook(book);

    }

}
11. JDBC Template 的增删改查

增删改的操作,都是调用jdbcTemplate对象中的update方法,主要的查询有多种不同的返回值和方式!

bean的xml文件:




    
    

    
    
    
        
        
        
        
     


    
    
        
        
    


Book实体类:

package com.itholmes.spring5.bean;

public class Book {

    private int user_id;
    private String user_name;
    private String user_password;

    public int getUser_id() {
        return user_id;
    }

    public void setUser_id(int user_id) {
        this.user_id = user_id;
    }

    public String getUser_name() {
        return user_name;
    }

    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }

    public String getUser_password() {
        return user_password;
    }

    public void setUser_password(String user_password) {
        this.user_password = user_password;
    }

    @Override
    public String toString() {
        return "Book{" +
                "user_id=" + user_id +
                ", user_name='" + user_name + ''' +
                ", user_password='" + user_password + ''' +
                '}';
    }
}

BookDao层的接口:

package com.itholmes.spring5.dao;

import com.itholmes.spring5.bean.Book;

import java.util.List;

public interface BookDao {
    public void add(Book book);
    public void update(Book book);
    public void delete(String id);
    public int selectCount();
    public Book findBookInfo(String id);
    public List findBookList();
}

实现BookDao接口的实现类(重点,多看查询操作是怎么完成的):

package com.itholmes.spring5.dao;

import com.itholmes.spring5.bean.Book;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public class BookDaoImpl implements BookDao{

    //注入jdbcTemplate
    @Autowired
    private JdbcTemplate jdbcTemplate;

    //添加操作
    @Override
    public void add(Book book) {

        String sql = "insert into `user` (`user_name`,`user_password`)values(?,?)";

        //重点:jdbcTemplate中可以通过update方法来实现添加操作。
        //update方法有两个参数:
        //第一个参数:String sql 是sql语句
        //第二个参数:Object... args(可变参数,也可以添加数组!) 是sql语句我们需要传入?参数,这个就是我们要传入的不同类型的值。
        //int update = jdbcTemplate.update(sql, book.getBook_name(), book.getBook_password());

        //因为args是一个可变参数,我们也可以添加个数组啥的。
        Object[] args = {book.getUser_name(), book.getUser_password()};
        int update = jdbcTemplate.update(sql, args);

        System.out.println(update);

    }

    //修改方法
    @Override
    public void update(Book book) {
        String sql = "update `user` set user_name=?,user_password=? where user_id=?";
        Object[] args = {book.getUser_name(),book.getUser_password(),book.getUser_id()};
        int update = jdbcTemplate.update(sql, args);
        System.out.println(update);
    }

    //删除方法
    @Override
    public void delete(String id) {
        String sql = "delete from `user` where user_id=?";
        int update = jdbcTemplate.update(sql, id);
        System.out.println(update);
    }

    //查询表中记录数(返回某个值)
    @Override
    public int selectCount() {
        String sql = "select count(*) from `user`";
        //查询操作和上面的增删改不同,它分为很多不同的方法,要牢记!!!
        Integer query = jdbcTemplate.queryForObject(sql, Integer.class);
        return query;
    }

    //查询表中数据,进而返回一个对象(返回对象)
    @Override
    public Book findBookInfo(String id) {
        String sql = "select * from `user` where user_id=?";
        //下面调用的是和上面重载类型差不多的方法,多了一个参数rowMapper参数。
        //rowMapper是一个接口,返回不同类型数据,使用这个接口里面的实现类完成数据的封装。
        Book book = jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper(Book.class), id);
        return book;
    }

    //查询表中的多个数据,进而返回一个集合(返回集合)
    @Override
    public List findBookList() {
        String sql = "select * from `user`";
        //同样和上面相同也是有三个参数,返回结果为集合,只不过这里第三个参数给sql传递值,就是sql里面的?,没有所以省略就好。
        List query = jdbcTemplate.query(sql, new BeanPropertyRowMapper(Book.class));
        return query;
    }


}

service层的BookService类:

package com.itholmes.spring5.service;


import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.dao.BookDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class BookService {

    //注入dao
    @Autowired
    private BookDao bookDao;

    //添加方法
    public void addBook(Book book){
        bookDao.add(book);
    }

    //修改方法
    public void updateBook(Book book){
        bookDao.update(book);
    }

    //删除方法
    public void deleteBook(String id){
        bookDao.delete(id);
    }

    //查询表中记录数(返回某个值)
    public int selectBookCount(){
        int i = bookDao.selectCount();
        return i;
    }

    //查询数据库中的某个对象(返回某个对象)
    public Book selectBook(String id){
        return bookDao.findBookInfo(id);
    }

    //查询数据库中的多个数据(返回集合)
    public List selectBookList(){
        return bookDao.findBookList();
    }
}

测试类Test类:


import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.Iterator;
import java.util.List;

public class TestBook {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");

        BookService service = context.getBean("bookService", BookService.class);

        //1.测试增加
        //Book book = new Book();
        //book.setUser_name("张三");
        //book.setUser_password("zhangsan");
        //service.addBook(book);

        //2.测试修改
        //Book book2 = new Book();
        //book2.setUser_id(1);
        //book2.setUser_name("itholmes");
        //book2.setUser_password("456");
        //service.updateBook(book2);

        //3.测试删除
        //service.deleteBook("2");

        //查询分为3种:返回某个值,返回某个对象,返回某个集合。
        //4.测试查询count(*)数量
        int i = service.selectBookCount();
        System.out.println(i);

        //5.测试返回得到book对象类型
        //注意返回对象的属性值,必须与数据库的字段值对应起来,不然得不到数据!!
        Book book = service.selectBook("1");
        System.out.println(book.toString());


        //6.测试返回得到集合类型
        List books = service.selectBookList();
        System.out.println("------------");
        System.out.println(books);//这里可以直接打印

        System.out.println("------------");
        //遍历方式一:迭代器遍历
        Iterator iterator = books.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        System.out.println("------------");
        //遍历方式二:强化for循环
        for (Book b : books){
            System.out.println(b);
        }
    }
}
12. JdbcTemplate 的批量操作

批量修改,删除,添加都是,使用的jdbcTempate中的batchUpdate方法:

该方法有两个参数:

  • 参数一:sql语句。
  • 参数二:List集合,添加多条记录数据。

仅仅举一个添加操作,都是一样的:

//批量添加
public void batchAddBook(List batchArgs){
    String sql = "insert into `user` (`user_name`,`user_password`)values(?,?)";
    //batchUpdate方法将list集合中的内容,批量插入数据库中
    int[] ints = jdbcTemplate.batchUpdate(sql, batchArgs);
    System.out.println(Arrays.toString(ints));
}

同样,我们测试一下:

import com.itholmes.spring5.bean.Book;
import com.itholmes.spring5.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class TestBook {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("beans1.xml");

        BookService service = context.getBean("bookService", BookService.class);
        
        //注意List的用法:
        Object[] o1 = {"李四","zxc"};
        Object[] o2 = {"李五","zxc"};
        Object[] o3 = {"李六","zxc"};

        List batchArgs = new ArrayList<>();

        batchArgs.add(o1);
        batchArgs.add(o2);
        batchArgs.add(o3);

        service.batchAdd(batchArgs);
    }

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/696770.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号