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

Spring相关知识复习

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

Spring相关知识复习

Spring框架

Spring框架是一个集众多设计模式于一身的开源的、轻量级的项目管理框架。致力于JAVAEE轻量级解决方案。

轻量级解决方案:提供一个以简单的、统一的、搞笑的方式构造整个应用,并且可以将单层框架以最佳的组合糅合在一起建立一个连贯的体系

 Spring框架的核心作用

Spring框架用来管理[创建|使用|销毁]项目中的组件,由于Spring框架可以帮我们生产项目中组件对象,因此也习惯称Spring是一个工厂|容器

组件:项目中的service,dao,controller都是项目中的组件

Spring框架通常不管理对实体类对象创建

环境搭建

引入依赖

引入配置文件

创建组件

工厂管理




    
    
    

启动工厂测试

 public static void main(String[] args) {
		//启动工厂
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
		//获取对象
        UserDAO userDAO = (UserDAO) context.getBean("userDAO");

        userDAO.save("小黑");
    }
Spring框架中的核心思想 IOC[控制反转]

IOC (inversion of controll)        控制反转

将对象的创建由原来的方式转移到配置文件中,交给Spring工厂来创建对象

DI  (dependcy Injection)           依赖注入

Spring不仅要创建对象,还要建立类与类之间的关系,因此在控制反转的基础啊上又提出了依赖注入的概念

Set方式注入





    
        xxx
        qiqi
        jinjin
    


    
        aaa
        bbb
        ccc
    



    
        
        
        
    



    
        jdbc:mysql://localhost:3306
        com.mysql.jdbc.Driver
        root
        root
    

注意:引用类型使用ref属性注入,基本类型使用value属性注入

构造注入




    
        111223456
        223456445
        333456445
    
自动注入

autowire="byName"
根据注入的属性名与配置文件中的bean的id匹配,一致则注入,不一致报错

autowire="byType"
根据注入的属性类型,与配置文件中的类型匹配,类型一致注入(在多个实现类时,会产生歧义)

无论使用以上哪种方式注入都需要为属性提供set方法

bean的创建模式

singleton:单例        默认

在工厂中全局唯一,只创建一次

prototype:多例

全局不唯一,每次使用都会创建一个新的对象

                service   dao   -------------->  singleton
                controller        --------------->   propotype

bean的生产原理

原理:反射+构造方法

userDaoImpl userDao =(UserDaoImpl)Class.forName("com.tjcu.dao.UserDaoImpl").newInstance();
System.out.println(userDao);

bean的生命周期

何时创建

        随着工厂启动,所有单例bean随之创建  非单例的bean,每次使用时创建

何时销毁

        工厂关闭,所有bean随之销毁(注意:Spring不会负责多例bean的销毁)

bean工厂创建对象的好处

1、使用配置文件管理Java类,在生产环境中更换类的实现时不需要重新部署,修改文件即可

2、Spring默认使用单例的模式创建bean,减少内存的占用

3、通过依赖注入建立了类与类之间的关系(使Java之间关系更为清晰,方便了维护与管理)

代理

什么是代理?
        代理指的是Java中的一种设计模式

为什么需要代理?
        很多时候除了当前类能够提供的功能外,我们还需要补充一些额外功能

代理的作用?
        代理对象可以在客户和目标对象之间起到中介作用,从而外目标对象增添额外的功能

静态代理的开发

目标类|对象(target):被代理类称之为目标类|或者被代理的对象称之为目标对象

目标对象

        开发代理的原则:代理类和目标类的功能一致且实现相同的接口,同时代理类中依赖于目标类对象

开发静态代理类

//静态代理类
//开发原则:代理类和目标类实现相同接口,依赖于真正的目标类
public class UserServiceStaticProxy implements UserService {

    //真正的目标类 //target 原始业务逻辑对象
    private UserService userService;
    public void setUserService(UserService userService) {
        this.userService = userService;
    }

    @Override
    public void save(String name) {
        try {
            System.out.println("开启事务");
            userService.save(name);//调用真正业务逻辑方法
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    @Override
    public void delete(String id) {
        try {
            System.out.println("开启事务");
            userService.delete(id);//调用真正业务逻辑方法
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    @Override
    public void update() {
        try {
            System.out.println("开启事务");
            userService.update();//调用真正业务逻辑方法
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    @Override
    public String findAll(String name) {
        try {
            System.out.println("开启事务");
            String result = userService.findAll(name);//调用真正业务逻辑方法
            System.out.println("提交事务");
            return result;
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public String findOne(String id) {
        try {
            System.out.println("开启事务");
            //调用目标类方法
            String one = userService.findOne(id);//调用真正业务逻辑方法
            System.out.println("提交事务");
            return one;
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
        return null;
    }
}

更改目标实现类

public class UserServiceImpl implements UserService {
    @Override
    public void save(String name) {
        System.out.println("处理业务逻辑,调用DAO~~~");
    }

    @Override
    public void delete(String id) {
        System.out.println("处理业务逻辑,调用DAO~~~");
    }

    @Override
    public void update() {
        System.out.println("处理业务逻辑,调用DAO~~~");
    }

    @Override
    public String findAll(String name) {
        System.out.println("处理业务逻辑,调用DAO~~~");
        return name;
    }

    @Override
    public String findOne(String id) {
        System.out.println("处理业务逻辑,调用Dao~~~");
        return id;
    }
}

配置静态代理类

		
    

    
    
        
        
    

调用代理方法

ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
UserService userServiceStaticProxy = (UserService) context.getBean("userServiceStaticProxy");
userServiceStaticProxy.save("小黑");

问题:在开发中我们书写的不仅仅是一个业务层,我们的业务层会有很多,如果为每一个业务类开发一个静态代理类,造成业务代码冗余的问题

为业务层在运行过程中动态创建代理类,通过代理类解决业务层中业务代码冗余的问题

动态代理的原理

public class TestDynamicProxy {
    public static void main(String[] args) {
        final UserService userService =  new UserServiceImpl();
        //参数1:当前线程类加载器
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        //参数2:生成代理类的接口类型
        Class[] classes =  new Class[]{UserService.class};
        //参数3:通过代理类对象调用方法时会有限进入参数三中的invoke方法
        //返回值就是动态代理对象
        UserService userServiceProxy = (UserService) Proxy.newProxyInstance(contextClassLoader, classes, new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                try{
                    System.out.println("开启事务");//附加操作
                    Object invoke = method.invoke(userService, args);
                    System.out.println("提交事务");//附加操作
                    return invoke;
                }catch (Exception e){
                    System.out.println("回滚事务");//附加操作
                }
                return null;
            }
        });
        userServiceProxy.save("小黑");
    }
}
AOP[面向切面编程]

AOP(Aspect Oriental Programing)面向切面的编程

通知(Advice):除了目标方法以外的操作都称之为通知

切入点(PointCut):要为哪些类中的哪些方法加入通知

切面(Aspect):通知+切入点

通知分类 步骤
    
        
        
        c.配置切面
        
            
            
            <--advice-ref:已有通知的id  pointcut-ref:已有切入点的id-->
            
        

    
        //启动工厂
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("before/spring.xml");
        //获取组件
        UserService userSerivce = (UserService) context.getBean("userService");
        System.out.println(userSerivce.getClass());
        //调用方法 通过代理类调用方法
        userSerivce.save("小黑");
通知[接口]

1.前置通知(MethodBeforeAdvice)的使用

 2.环绕通知(MethodInterceptor)的使用

 3.返回后(后置)(AfterReturningAdvice)通知

 4.异常(ThrowAdvice)通知

目标方法正常执行结束,执行后置通知

如果目标方法执行出现异常,才执行异常通知

切入点表达式

作用:通知Spring框架要为哪些类生成动态代理对象

1.execution方法级别的切入点表达式

execution[访问修饰符]返回值 包名.类名.方法名(参数表)        [  ]中的内容可以省略

注意:书写访问修饰符 返回值 包名 类名 方法名时 都支持通配    *表示任意

书写参数表时支持通配 ..表示任意

execution常用方式:

 注意:方法级别的切入点表达式尽可能精准,否则程序可能出现异常

2、within类级别的切入点表达式        精确到类

1.语法
    within(包.类)

    书写包名 类名时 也支持通配 *表示任意
2.示例
    within(com.baizhi.service.*) 
            包: com.baizhi.service
            类: 所有类中所有方法不关心返回值和参数
    
    within(com.baizhi.service.UserServiceImpl)
            包: com.baizhi.service
            类: UserServiceImpl类中所有方法不关心返回值和参数

3、注意[自定义注解]

注意:within的效率高于execution表达式,推荐使用within表达式

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

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

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