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

Spring的学习

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

Spring的学习

Spring
  • 这个知识重要吗?有什么用?
  • Spring概述
    • Spring是什么?
    • Spring 两个核心:IOC 以及 AOP
    • Spring 入门框架
  • IOC
    • 什么是IOC
    • IOC底层原理
    • BeanFactory 接口
    • Bean 作用域
    • FactoryBean
    • Bean 的生命周期
    • 加入后置处理器
    • Bean 管理
    • 基于 XML 文件进行 Bean 管理
      • 创建对象
      • 注入属性(DI依赖注入)
        • P标签注入
        • 有参构造注入
        • 注入的属性为 null 或者含有特殊符号
        • 外部 Bean 的引用注入
        • 内部Bean注入以及级联属性
        • 集合注入,以及集合添加元素
        • XML 自动装配
        • XML外部属性文件
    • 基于注解进行 Bean 管理
      • 创建对象
      • 注入属性
      • 注解类,获取外部文件,开启扫描
  • AOP
    • 什么是AOP,起到什么作用,怎么实现的?
    • AOP术语
    • AOP 动态代理的两种情况
    • 使用 JDK 代理实现 AOP 操作
    • 使用 Spring & AspectJ 实现 AOP操作
      • 切入表达式
      • 实现 AOP 操作
    • JDBCtemplate
  • 事务管理
      • 使用注解类实现银行转账功能
    • 整合 log4j
  • 指导复习的问题
  • 容易犯的错误


这个知识重要吗?有什么用?
Spring概述 Spring是什么?

是一个轻量级开源的 JavaEE 框架,用来解决企业应用开发的复杂性。

  • 轻量级:需要依赖的文件少,小,可以单独使用。
  • 开源:源代码开放。
  • 框架:让开发更加方便、简洁。
Spring 两个核心:IOC 以及 AOP
  • IOC(控制翻转):将创建对象的过程交给 Spring 进行管理。
  • AOP(面向切面):可以不修改源代码的情况下,对代码功能进行增强。
Spring 入门框架

(1)添加依赖


            
                org.springframework
                spring-core
                4.3.7.RELEASE
            
            
                org.springframework
                spring-beans
                4.3.7.RELEASE
            
            
                org.springframework
                spring-context
                4.3.7.RELEASE
            
            
            
            
                org.springframework
                spring-jdbc
                4.3.7.RELEASE
            
            
                org.springframework
                spring-tx
                4.3.7.RELEASE
            
            
            
                org.springframework
                spring-web
                4.3.7.RELEASE
            
            
                org.springframework
                spring-webmvc
                4.3.7.RELEASE
            
            
            
	            org.springframework
	            spring-test
	            4.3.7.RELEASE
            
			
			
	            org.projectlombok
	            lombok
	            1.18.20
        	
			
		        
		            junit
		            junit
		            4.12
		
		        
		        
		            junit
		            junit
		            4.12
		            test
		        
        

(2)创建对象,创建 spring-config.xml文件,在配置文件中创建 bean 标签,将对象类加载到配置文件中
(3)创建测试类,通过ClassPathXmlApplicationContext获取context对象,再获取对象

public class UserTest {
    @Test
    public void test() {
        ClassPathXmlApplicationContext context = 
        new ClassPathXmlApplicationContext("spring-config.xml");

        User user = context.getBean("user", User.class);

        user.doThing();
    }
}

IOC 什么是IOC

IOC(控制反转)是一种设计原则,在对象创建时,通过一个调控系统将对象的引用传递给它,目的是减少耦合。


IOC底层原理

使用到了 XML解析、工厂模式、反射。

IOC实现解耦合:XML配置文件配置对象,创建工厂类,通过反射创建对象。


BeanFactory 接口

1、IOC 思想基于 IOC 容器完成,IOC 容器底层就是对象工厂

2、Spring 提供 IOC 容器实现两种方式:(两个接口)

  • BeanFactory:IOC 容器基本实现,是 Spring 内部的使用接口,不提供开发人员进行使用
    特点:加载配置文件时候不会创建对象,在获取对象(使用)才去创建对象

  • ApplicationContext:BeanFactory 接口的子接口,提供更多更强大的功能,一般由开发人
    员进行使用
    特点:加载配置文件时候就会把在配置文件对象进行创建

ApplicationContext 实现类

		// 类路径加载
		ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext();
		// 磁盘路径加载
        FileSystemXmlApplicationContext context1 = new FileSystemXmlApplicationContext();

Bean 作用域

Bean 作用域指的就是在 IOC 容器中,Bean 是单例还是多例的。
单例(默认):所有请求由一个对象处理。
多例:多个请求由多个对象进行处理。

在 标签中,修改 scope = “protorype” 可以将 Bean 修改成多例的,此时不再是加载配置文件时进行加载对象,而是在 调用 getBean 方法时,重新创建一个对象。


FactoryBean

Spring 中有两种类型的 Bean ,普通 Bean 以及 工厂Bean

普通Bean
定义的类型与实际返回的类型相同

工厂Bean
配置文件中定义的类型和实际返回的类型可以不同,目的是从Spring的角度实现创建不同的Bean对象。

public class UserFactory implements FactoryBean {
    
    @Override
    public User getObject() throws Exception {
        return new User();
    }

    
    @Override
    public Class getObjectType() {
        return User.class;
    }

    
    @Override
    public boolean isSingleton() {
        return false;
    }
}
@Test
    public void test() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
        User bean = context.getBean("userFactory", User.class);

        bean.user();
    }
Bean 的生命周期

默认有五步生命周期

无参构造创建 → 注入属性(set方法) → 初始化(需要配置方法)→ 使用 → 销毁(手动,需要配置方法)

加入后置处理器以后

无参构造创建 → 注入属性(set方法) → 后置处理器 → 初始化(需要配置方法)→  后置处理器 → 使用 → 销毁(手动,需要配置方法)

配置初始化、销毁方法

 标签中有 init-method  以及  destroy-method   将Bean类中方法名赋值给它们,就可以完成初始化、销毁方法的定义,注意的是销毁需要使用手动调用销毁  context.close()

加入后置处理器

创建一个类实现 BeanPostProcessor ,并重写两个方法(before、after),这个类也需要在配置文件中进行配置,当配置文件配置了后置处理器后,会为全部的 Bean 对象添加后置处理器。


Bean 管理

Bean管理指的是两个操作,Spring 创建对象,Spring 注入属性。

基于 XML 文件进行 Bean 管理 创建对象

在 Spring 配置文件中,通过 标签进行创建以及配置属性,创建时使用无参构造函数进行创建。

  • id:唯一标识
  • name:唯一标识,相比于 ID ,可以添加特殊符号
  • class:对象所在的包类路径
注入属性(DI依赖注入)

核心是 set 方法
标签中,添加标签,底层会将属性名首字母大写,添加前缀 set 调用对应的方法。

  • name :属性名
  • value:属性值

P标签注入

本质还是使用 set 方法进行注入,使用命名空间简化了属性,在 标签中,添加p:属性名=属性值


有参构造注入

使用标签调用对象的构造方法进行注入,要求有对应参数的构造方法

  • name:属性名
  • value:属性值

注入的属性为 null 或者含有特殊符号
  • null

	

  • 特殊符号

	  >]]>  


外部 Bean 的引用注入

—个Bean标签 A 引用了另外—个Bean标签 B,B是在A外进行注册的,那么A就称为引入外部Bean B



内部Bean注入以及级联属性

—个Bean标签A引用了另外一个Bean标签B,B是在A内部进行注册的,那么A就称为引入内部 Bean
使用标签,在标签内进行的注册,同时这个bean也能配置属性,就称为级联属性

集合注入,以及集合添加元素


XML 自动装配

自动装配指的是根据装配规则,Spring 自动将属性进行匹配注入,在需要自动装配的 Bean 中添加属性 autowire,底层是调用了对应的 Set 方法。

  • ByName:根据属性名匹配对应的 Bean
  • ByType:根据属性类型匹配对应的 Bean

XML外部属性文件

需要引入 Context 命名空间,使用标签,它是一个单标签,引入外部文件,使用 ${key} 进行取值。

xmlns:context="http://www.springframework.org/schema/context"
  • location:声明文件地址


    
        
    
基于注解进行 Bean 管理 创建对象

1、在对象上进行Bean的声明,告诉 Spring 哪些类需要进行创建,提供了多个注解帮助对象的创建,是一种规范。

  • @Component 普通 Bean
  • @Service Service 层
  • @Controller Controller 层
  • @Repository Dao 层

2、开启组件扫描

XML形式:

配置扫描范围

设置扫描的范围


        
    

排除扫描的范围


        
    
注入属性
  • @Autowired 用于注释属性,根据属性联系进行自动装配,内部封装了 Set 方法。
  • @Qualifier 配合@Autowired使用,当注入属性有多个实现类时,使用@Qualifier(value = "类名")指定实现类进行注入。
  • @Resource 根据类型或者名称进行注入,当使用 name 属性时,就根据名称进行注入,否则根据联系,是 JavaX 提供的注解。
  • @Value 注入普通联系的属性,使用 value 属性进行赋值,会将它转换为注入属性的联系,如果不能转换,将抛出异常。

注解类,获取外部文件,开启扫描
  • @Configuration 表示当前类为注解类
  • @PropertySource 引入外部文件,使用 ${key} 进行取值
  • @ComponentScan 开启组件扫描,使用basePackages 声明扫描位置
@PropertySource(value = "classpath:database.properties")
@Configuration
@ComponentScan(basePackages = {"com.wuqiyong"})
public class MyConfig {
	使用 key 来获取外部文件的值
}

使用 AnnotationConfigApplicationContext(ConfigClass.class) 加载配置文件


AOP 什么是AOP,起到什么作用,怎么实现的?
  • AOP是面向切面编程,利用AOP可以使业务逻辑各个部分进行分离,使得耦合性降低。
  • 将不属于业务逻辑的代码从业务中划分出来,即在不修改源代码的情况下,在主干功能里面添加新的功能。
  • 是通过创建一个代理对象,在代理对象中额外添加逻辑代码从而增强。

AOP术语
  • 连接点 在一个类中,哪些方法可以被增强,那么这个方法就称为连接点。
  • 切入点 在一个类中,实际被增强的方法称为切入点
  • 通知(增强) 对主体代码进行补充的逻辑代码部分称为通知(增强)
  • 切面指的是一个动作,把通知应用到切入点的过程称为切面
AOP 动态代理的两种情况
  • 当有接口时,使用 JDK 动态代理 创建接口实现类的代理对象,来进行增强方法。
  • 没有接口时,使用 CGLIB 动态代理 创建当前类的子类,通过子类的代理对象,来进行增强方法。
使用 JDK 代理实现 AOP 操作
  • Proxy.newProxyInstance() 得到一个代理对象
  • 类加载器
  • 需要增强方法所在类实现的接口
  • 代理对象类,需要实现 InvocationHandler里面写增强方法
public interface User {
    void user();
}


class UserImpl implements User {

    @Override
    public void user() {
        System.out.println("userImpl");
    }
}

class UserPlus implements InvocationHandler {
    private Object object;

    public UserPlus(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        System.out.println("before");

        Object invoke = method.invoke(object, args);

        System.out.println("after");

        return invoke;
    }
}

class JDKProxy {
    public static void main(String[] args) {
        Class[] interfaces = new Class[]{User.class};

        UserImpl user = new UserImpl();

        User userPlus = (User) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserPlus(user));

        userPlus.user();
    }
}


使用 Spring & AspectJ 实现 AOP操作

Spring 框架一般都是基于 AspectJ 实现 AOP 操作

AspectJ 是独立的AOP框架,将 spring 和 AspectJ 一起实现AOP操作

切入表达式

切入表达式就是声明在哪一个类中哪一个方法需要进行增强
语法结构 execution([权限修饰符] [返回类型] [类全路径] [方法名称]([参数列表]))

  • 权限修饰符:* 代表全部权限
  • 返回联系:可以省略
  • 类全路径 . 方法名:代表增强当前方法,* 代表全部方法
  • 参数列表:可以使用 .. 省略
实现 AOP 操作

1、添加依赖

	
	    org.springframework
	    spring-aspects
	    5.2.7.RELEASE
	
	
	
	    org.aspectj
	    aspectjtools
	    1.9.5
	
	
	
	    aopalliance
	    aopalliance
	    1.0
	
	
	
	    org.aspectj
	    aspectjweaver
	    1.9.0
	
	
	
	    cglib
	    cglib
	    3.3.0
	

2、代码实现



    
public class AspectJ {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");

        Emp emp = context.getBean("emp", Emp.class);

        emp.emp();

    }
}

@Component
class Emp {
    public void emp() {
        System.out.println("Emp !!!");
    }
}

@Component
@Aspect
class EmpPlus {

    // 提取相同的切入点

    @Pointcut(value = "execution(* com.wuqiyong.Review.Emp.emp(..))")
    public void pointCut() {
    }


    //前置通知
    //@Before 注解表示作为前置通知
    @Before(value = "pointCut()")
    public void before() {
        System.out.println("before.........");
    }
    //后置通知(返回通知)
    @AfterReturning(value = "pointCut()")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }
    //最终通知
    @After(value = "pointCut()")
    public void after() {
        System.out.println("after.........");
    }
    //异常通知
    @AfterThrowing(value = "pointCut()")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }
    //环绕通知
    @Around(value = "pointCut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws
            Throwable {
        System.out.println("环绕之前.........");
        //被增强的方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后.........");
    }
}

3、使用注解类实现

public class AspectJ {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AspectJConfig.class);
        Emp emp = context.getBean("emp", Emp.class);
        emp.emp();
    }
    
}

@Component
class Emp {
    public void emp() {
        System.out.println("Emp !!!");
    }
}

@ComponentScan(basePackages = {"com.wuqiyong.Review"})
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass = true)
class AspectJConfig {
}

@Component
@Aspect
class EmpPlus {

    // 提取相同的切入点

    @Pointcut(value = "execution(* com.wuqiyong.Review.Emp.emp(..))")
    public void pointCut() {
    }


    //前置通知
    //@Before 注解表示作为前置通知
    @Before(value = "pointCut()")
    public void before() {
        System.out.println("before.........");
    }
    //后置通知(返回通知)
    @AfterReturning(value = "pointCut()")
    public void afterReturning() {
        System.out.println("afterReturning.........");
    }
    //最终通知
    @After(value = "pointCut()")
    public void after() {
        System.out.println("after.........");
    }
    //异常通知
    @AfterThrowing(value = "pointCut()")
    public void afterThrowing() {
        System.out.println("afterThrowing.........");
    }
    //环绕通知
    @Around(value = "pointCut()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws
            Throwable {
        System.out.println("环绕之前.........");
        //被增强的方法执行
        proceedingJoinPoint.proceed();
        System.out.println("环绕之后.........");
    }
}



JDBCtemplate

JDBCemplate 是 Spring 框架对 JDBC 进行的封装
1、导入依赖

		
            com.alibaba
            druid
            1.2.3
        
		
            mysql
            mysql-connector-java
            5.1.37
        

2、配置数据库连接池


        
        
        
        
    

    
        
    

3、编写代码

  • update 增删改
  • queryForObject 查询一个对象,包括特殊值查询,使用 BeanPropertyRowMapper 封装自定义类。
  • query 查询多个对象,使用 BeanPropertyRowMapper 封装自定义类。

事务管理

事务是添加到 Service 层的,在 Spring 中有编程型事务(通过编程)以及声明型事务(通过配置文件),声明型事务又可以通过注解以及 XML 文件实现,底层使用了 AOP。

1、创建事务管理器


	 
	 


2、开启事务注解

  • 引入名称空间 tx
  • 开启事务注解




3、在 Service 类或方法上添加 @Transactional

  • @Transactional 添加到类上,该类所有方法开启事务,添加到方法上,当前方法开启事务。

    在 @Transactional 中有多个重要属性

    • propagation 事务传播行为,即当多个方法进行调用时,有普通方法以及事务方法,那么应该怎么处理。

      • REQUIRED 如果有事务在运行,那么当前方法就在这个事务内运行,否则,就创建一个新的事务,并在自己的事务内运行。
      方法 A 调用 方法 B
      	当 A 有事务时,B 方法使用 A 方法中的事务
      	当 A 没有事务时,创建一个新的事务
      	A、B任意⼀个⽅法异常(默认是RuntimeException和Error)都会导致A、B的操作被回滚。
      
      • REQUIRED_NEW 当前方法必须启动新事务,并在自己的事务中内运行,如果有事务正在运行,应该将它挂起。
      	方法 A 调用 方法 B
      		如果 A 存在一个事务,那么会将 A 的事务挂起
      		新建一个属于 B 的事务,等 B 的事务执行完成以后才会执行 A 的事务
      	如果 A 发生异常,只会回滚 A 不会回滚 B 
      	如果 B 发生异常 B 一定会进行回滚,抛出异常给 A ,如果 A catch 住了,那么 A 不会回滚,否则 A 也会回滚。
      

ioslation 事务隔离级别

  • Isolation.READ_COMMITTED
  • Isolation.REPEATABLE_READ

timeout 超时时间

  • 设置事务需要在一定的时间内进行提交,否则进行回滚,默认值为 -1 单位是秒。

readOnly 是否只读

  • false 增删查改
  • true 只能查询

rollbackFor noRollbackFor 当出现哪些异常时回滚/不回滚

使用注解类实现银行转账功能
public class Transaction {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(TxConfig.class);
        MyService myService = context.getBean("myService", MyService.class);
        myService.transfer();
    }
}

@Service
@Transactional
class MyService {

    @Autowired
    Dao dao;

    public void transfer() {
        dao.transfer1();

        System.out.println(1 / 0);

        dao.transfer2();
    }
}

@Repository
class Dao {

    @Autowired
    JdbcTemplate jdbcTemplate;

    public void transfer1() {
        String sql = "update user_table set balance = balance - 100 where user = ?";

        jdbcTemplate.update(sql, "AA");

    }

    public void transfer2() {
        String sql = "update user_table set balance = balance + 100 where user = ?";
        jdbcTemplate.update(sql, "BB");
    }


}

@Configuration
@ComponentScan(basePackages = {"com.wuqiyong"})
@EnableTransactionManagement
@PropertySource(value = "classpath:database.properties")
class TxConfig {
    
    @Value("${jdbc.url}")
    private String url;

    @Value("${jdbc.driver}")
    private String driver;

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;



    @Bean
    public DruidDataSource getDruidDataSource() {
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setUrl(url);
        dataSource.setDriverClassName(driver);
        dataSource.setUsername(username);
        dataSource.setPassword(password);

        return dataSource;
    }


    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource);

        return jdbcTemplate;
    }


    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);

        return dataSourceTransactionManager;
    }
}
整合 log4j

1、引入依赖
2、创建 log4j2.xml


指导复习的问题
  • 使用 JDK 代理实现 AOP 操作
  • 使用 AspectJ 实现 AOP 操作
  • 使用 JDBCtemplate 对数据库进行增删查(一个对象,多个对象,记录条数)改
  • 使用事务管理实现转账功能

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

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

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