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

Spring运用

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

Spring运用

1 现有业务层开发存在问题

1.定义业务接口的代码如下:

package com.txw.service;


@SuppressWarnings("all")  // 注解警告信息
public interface UserService {
    
    public void save(String name);

    
    public void delete(String id);

    
    public void update();

    
    public String findAll(String name);

    
    public String findOne(String id);
}

如图所示:
2.实现业务接口的代码如下:

package com.txw.service.impl;

import com.txw.service.UserService;

@SuppressWarnings("all")  // 注解警告信息
public class UserServiceImpl implements UserService {

    
    @Override
    public void save(String name) {
        try {
            System.out.println("开启事务");
            System.out.println("处理业务逻辑,调用DAO~~~");
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    
    @Override
    public void delete(String id) {
        try {
            System.out.println("开启事务");
            System.out.println("处理业务逻辑,调用DAO~~~");
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    
    @Override
    public void update() {
        try {
            System.out.println("开启事务");
            System.out.println("处理业务逻辑,调用DAO~~~");
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
    }

    
    @Override
    public String findAll(String name) {
        try {
            System.out.println("开启事务");
            System.out.println("处理业务逻辑,调用DAO~~~");
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
        return name;
    }

    
    @Override
    public String findOne(String id) {
        try {
            System.out.println("开启事务");
            System.out.println("处理业务逻辑,调用DAO~~~");
            System.out.println("提交事务");
        }catch (Exception e){
            System.out.println("回滚事务");
            e.printStackTrace();
        }
        return id;
    }
}

如图所示:
问题:从上图中可以看出,现有业务层中控制事务代码出现了大量的冗余,如何解决现有业务层出现的冗余问题?
3.编写spring.xml的代码如下:



    

如图所示:
4.编写UserServiceTest的代码如下:

package com.txw.test;

import com.txw.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@SuppressWarnings("all")  // 注解警告信息
public class UserServiceTest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.save("Adair");
    }
}

如图所示:

2 代理引言 2.1 什么是代理

代理: 指的是java中的一种设计模式。

2.2 为什么需要代理

很多时候除了当前类能够提供的功能外,我们还需要补充一些额外功能。

2.3 代理的作用

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

2.4 代理图例

3 静态代理的开发

目标类|对象(target):被代理类称之为目标类|或者被代理的对象的称之为目标对象。
开发代理的原则: 代理类和目标类功能一致且实现相同的接口,同时代理类中依赖于目标类对象。

3.1 开发静态代理类

代码如下:

package com.txw.util;

import com.txw.service.UserService;

@SuppressWarnings("all")  // 注解警告信息
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;
    }
}

如图所示:

3.2 更改目标实现类

代码如下:

package com.txw.service.impl;

import com.txw.service.UserService;

@SuppressWarnings("all")  // 注解警告信息
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;
    }
}

如图所示:

3.3 配置静态代理类

代码如下:



    
    
    
    
        
        
    

如图所示:

3.4 调用代理方法

代码如下:

package com.txw.test;

import com.txw.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@SuppressWarnings("all")  // 注解警告信息
public class UserServiceTest {

    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        UserService serviceStaticProxy = (UserService) context.getBean("serviceStaticProxy");
        serviceStaticProxy.save("Adair");
    }
}

如图所示:

新的问题:往往在开发我们书写的不仅仅是一个业务层,两个业务层,而我们的业务层会有很多,如果为每一个业务层开发一个静态代理类,不仅没有减轻工作量,甚至让我们的工作量多了一倍不止怎么解决以上这个问题呢?
解决方案: 为业务层在运行过程中动态创建代理类,通过动态代理类去解决我们现有业务层中业务代码冗余的问题。

4 动态代理的原理

通过jdk提供的Proxy这个类,动态为现有的业务生成代理类。
参数一:当前线程类加载器。
参数二:生成代理类的接口类型。
参数三:通过代理类对象调用方法时会优先进入参数三中的invoke方Proxy.newProxyInstance(loader, interfaces, h);//返回值就是动态代理对象。

演示的代码如下:

package com.txw.test;

import com.txw.service.UserService;
import com.txw.service.impl.UserServiceImpl;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

@SuppressWarnings("all")  // 注解警告信息
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:
        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("小黑");
    }
}

5 AOP (Aspect Oriented Programming)编程

通知(Advice): 除了目标方法以外的操作都称之为通知。
切入点(PointCut): 要为哪些类中的哪些方法加入通知。
切面(Aspect): 通知 + 切入点。

5.1 通知分类

如图所示:

5.2 编程步骤

1.引入依赖,如图所示:

2.开发通知类
1.编写的EmpService的代码如下:

package com.txw.service;


@SuppressWarnings("all")  // 注解警告信息
public interface EmpService {
    public void ma();
    public void mb(String name);
    public String mc(String id);
}

如图所示:

2.编写的EmpServiceImpl的代码如下:

package com.txw.service.impl;

import com.txw.service.EmpService;

@SuppressWarnings("all")  // 注解警告信息
public class EmpServiceImpl implements EmpService {
    @Override
    public void ma() {
        System.out.println("处理 ma 核心业务逻辑");
    }

    @Override
    public void mb(String name) {
        System.out.println("处理 mb 核心业务逻辑");
    }

    @Override
    public String mc(String id) {
        System.out.println("处理 mc 核心业务逻辑");
        return id;
    }
}

如图所示:
3.配置切面
在spring1.xml添加的代码如下:



   
    
    
    
    
    
        
        
            
        
    

如图所示:
4.启动工厂测试
.编写SpringTest的代码如下:

package com.txw.test;

import com.txw.service.EmpService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {
    @Test
    public void test(){
        ApplicationContext context = new ClassPathXmlApplicationContext("spring1.xml");
         // 当前获取的核心业务对象 是通过动态代理生成的代理对象
        EmpService empService = (EmpService) context.getBean("empService");
        empService.ma();
    }
}

如图所示:

5.3 前置通知的使用

代码如下:

package com.txw.before;

import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

@SuppressWarnings("all")  // 注解警告信息
public class MyBoforeAdivce implements MethodBeforeAdvice {
    
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println("日志通知类记录方法的名字为:" +method);
    }
}

如图所示:

5.4 环绕通知的使用

如图所示:
代码如下:

package com.txw.before;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

@SuppressWarnings("all")  // 注解警告信息
public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation methodInvocation) throws Throwable {
        //  书写额外功能
        long begin = System.currentTimeMillis();
        System.out.println("方法开始执行!!!");
        // 调用核心业务对象 核心服务方法
        Object result = methodInvocation.proceed();// 放行 执行核心服务方法 等价于动态代理 method.invoke(new xxxServiceImpl,args)
        System.out.println("方法即将结束!!!");
        long end = System.currentTimeMillis();
        System.out.println("方法运行时长为:" + (end =begin));
       
        return result;
    }
}

如图所示:
在spring1.xml添加的代码如下:

 
    
    
    
        
        
    

如图所示:

5.5 返回后通知

代码如下:

package com.txw.before;

import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

@SuppressWarnings("all")  // 注解警告信息
public class AtferReturnimgAdvice implements AfterReturningAdvice {

    
    @Override
    public void afterReturning(Object o, Method method, Object[] objects, Object o1) throws Throwable {

    }
}

如图所示:
在spring1.xml添加的代码如下:


    
    
    
        
        
    

如图所示:

5.6 异常通知在spring1.xml添加的代码,如图所示:## 6 切入点表达表 6.1 execution方法级别的切入点表达式

如图所示:

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

6.2 within类级别的切入点表达式

1.语法如下:

within(包.类)

2.演示的代码,如图所示:

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

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

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

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