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

2022.1.17

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

2022.1.17

return关键字

1、返回值

2、结束运行该函数

注意:一个函数的返回值类型 是void,那么也可以出现return关键字,但是return关键字的后面不能有数据。

此时return表示结束程序的运行

break、continue与return的区别:

    break关键字是结束整个循环。continue关键字是结束某次循环。return关键字是结束一个函数。

java.lang.ThreadLocal

多线程中保证线程安全,一是加锁,二是ThreadLocal(工具类)类型的变量.当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全问题。

ThreadLocal是JDK包提供的,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的一个副本,在实际多线程操作的时候,操作的是自己本地内存中的变量,从而规避了线程安全问题 .

构造方法摘要
ThreadLocal()
          创建一个线程本地变量。

方法摘要
 Tget()
          返回此线程局部变量的当前线程副本中的值。
protected  TinitialValue()
          返回此线程局部变量的当前线程的初始值。
 voidremove()
          移除此线程局部变量的值。
 voidset(T value)
          将此线程局部变量的当前线程副本中的值设置为指定值。
package test;

public class ThreadLocalTest {

    static ThreadLocal localVar = new ThreadLocal<>();

    static void print(String str) {
        //打印当前线程中本地内存中本地变量的值
        System.out.println(str + " :" + localVar.get());
        //清除本地内存中的本地变量
        localVar.remove();
    }

    public static void main(String[] args) {
        Thread t1  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localVar.set("localVar1");
                //调用打印方法
                print("thread1");
                //打印本地变量
                System.out.println("after remove : " + localVar.get());
            }
        });

        Thread t2  = new Thread(new Runnable() {
            @Override
            public void run() {
                //设置线程1中本地变量的值
                localVar.set("localVar2");
                //调用打印方法
                print("thread2");
                //打印本地变量
                System.out.println("after remove : " + localVar.get());
            }
        });

        t1.start();
        t2.start();
    }
}

同一个ThreadLocal变量在父线程中被设置值后,在子线程中是获取不到的。(threadLocals中为当前调用线程对应的本地变量,所以二者自然是不能共享的):

package test;

public class ThreadLocalTest2 {

    //(1)创建ThreadLocal变量
    public static ThreadLocal threadLocal = new ThreadLocal<>();

    public static void main(String[] args) {
        //在main线程中添加main线程的本地变量
        threadLocal.set("mainVal");
        //新创建一个子线程
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("子线程中的本地变量值:"+threadLocal.get());
            }
        });
        thread.start();
        //输出main线程中的本地变量值
        System.out.println("mainx线程中的本地变量值:"+threadLocal.get());
    }
}
InheritableThreadLocal类 

可继承的线程局部变量

InheritableThreadLocal类继承了ThreadLocal类,并重写了childValue、getMap、createMap三个方法。其中createMap方法在被调用(当前线程调用set方法时得到的map为null的时候需要调用该方法)的时候,创建的是inheritableThreadLocal而不是threadLocals。同理,getMap方法在当前调用者线程调用get方法的时候返回的也不是threadLocals而是inheritableThreadLocal。

Java中的ThreadLocal详解 - 夏末秋涼 - 博客园


JoinPoint 对象

JoinPoint对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,就可以获取到封装了该方法信息的JoinPoint对象. 
常用api:

方法名功能
Signature getSignature();获取封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
Object[] getArgs();获取传入目标方法的参数对象
Object getTarget();获取被代理的对象
Object getThis();获取代理对象
ProceedingJoinPoint对象

ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中, 
添加了 
Object proceed() throws Throwable //执行目标方法 
Object proceed(Object[] var1) throws Throwable //传入的新的参数去执行目标方法 

@Aspect
@Component
public class aopAspect {
    
    @Pointcut("execution(* aopdemo.*.*(..))")
    public void declareJoinPointerexpression() {}
 
    
    @Before("declareJoinPointerexpression()")
    public void beforeMethod(JoinPoint joinPoint){
        System.out.println("目标方法名为:" + joinPoint.getSignature().getName());
        System.out.println("目标方法所属类的简单类名:" +        joinPoint.getSignature().getDeclaringType().getSimpleName());
        System.out.println("目标方法所属类的类名:" + joinPoint.getSignature().getDeclaringTypeName());
        System.out.println("目标方法声明类型:" + Modifier.toString(joinPoint.getSignature().getModifiers()));
        //获取传入目标方法的参数
        Object[] args = joinPoint.getArgs();
        for (int i = 0; i < args.length; i++) {
            System.out.println("第" + (i+1) + "个参数为:" + args[i]);
        }
        System.out.println("被代理的对象:" + joinPoint.getTarget());
        System.out.println("代理对象自己:" + joinPoint.getThis());
    }
 
    
    @Around("declareJoinPointerexpression()")
    public Object aroundMethod(ProceedingJoinPoint pjd){
        Object result = null;
 
        try {
            //前置通知
            System.out.println("目标方法执行前...");
            //执行目标方法
            //result = pjd.proeed();
            //用新的参数值执行目标方法
            result = pjd.proceed(new Object[]{"newSpring","newAop"});
            //返回通知
            System.out.println("目标方法返回结果后...");
        } catch (Throwable e) {
            //异常通知
            System.out.println("执行目标方法异常后...");
            throw new RuntimeException(e);
        }
        //后置通知
        System.out.println("目标方法执行后...");
 
        return result;
    }
}

@Component
public class TargetClass {
    
    public String joint(String str1, String str2) {
        return str1 + "+" + str2;
    }
}

public class TestAop {
    @Test
    public void testAOP() {
        //1、创建Spring的IOC的容器
        ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:bean.xml");
 
        //2、从IOC容器中获取bean的实例
        TargetClass targetClass = (TargetClass) ctx.getBean("targetClass");
 
        //3、使用bean
        String result = targetClass.joint("spring","aop");
        System.out.println("result:" + result);
    }
}
目标方法执行前...
目标方法名为:joint
目标方法所属类的简单类名:TargetClass
目标方法所属类的类名:aopdemo.TargetClass
目标方法声明类型:public
第1个参数为:newSpring
第2个参数为:newAop
被代理的对象:aopdemo.TargetClass@4efc180e
代理对象自己:aopdemo.TargetClass@4efc180e
目标方法返回结果后...
目标方法执行后...
result:newSpring+newAop


java.lang.Class类的getAnnotation()
public T getAnnotation(Class annotationClass)

如果存在该元素的指定类型的注释,则返回这些注释,否则返回 null。

// Java program to demonstrate 
// getAnnotation() method 
  
import java.util.*; 
import java.lang.annotation.*; 
  
// create a custom Annotation 
@Retention(RetentionPolicy.RUNTIME) 
@interface Annotation { 
  
    // This annotation has two attributes. 
    public String key(); 
  
    public String value(); 
} 
  
// call Annotation for method 
// and pass values for annotation 
@Annotation(key = "GFG", value = "GeeksForGeeks") 
public class Test { 
  
    public static void main(String[] args) 
        throws ClassNotFoundException 
    { 
  
        // returns the Class object for this class 
        Class myClass = Test.class; 
  
        System.out.println("Class represented by myClass:"
                           + myClass.toString()); 
  
        // Get the annotation 
        // using getAnnotation() method 
        System.out.println( 
            "Annotation of myClass:"
            + myClass.getAnnotation( 
                  Annotation.class)); 
    } 
}

输出:

Class represented by myClass:class Test
Annotation of myClass:@Annotation(key=GFG, value=GeeksForGeeks)
// Java program to demonstrate 
// getAnnotation() method 
  
import java.util.*; 
import java.lang.annotation.*; 
  
// Class with no annotations 
// getAnnotation() will return null 
public class Test { 
  
    public static void main(String[] args) 
        throws ClassNotFoundException 
    { 
  
        // returns the Class object for this class 
        Class myClass = Test.class; 
  
        System.out.println("Class represented by myClass:"
                           + myClass.toString()); 
  
        // Get the annotation 
        // using getAnnotation() method 
        System.out.println( 
            "Annotation of myClass:"
            + myClass.getAnnotation( 
                  Annotation.class)); 
    } 
}

输出:

Class represented by myClass:class Test
Annotation of myClass:null

Spring @Order注解的使用

浅谈Spring @Order注解的使用_明洋的专栏-CSDN博客_@order


spring @ConfigurationProperties注解的使用

该注解有一个prefix属性,通过指定的前缀,绑定配置文件中的配置,该注解可以放在类上,也可以放在方法上.

当将该注解作用于方法上时,如果想要有效的绑定配置,那么该方法需要有@Bean注解且所属Class需要有@Configuration注解。

Sring的有效运行是通过上下文(Bean容器)中Bean的配合完成的,Bean可以简单理解成对象,有些对象需要指定字段内容,那么这些内容我们可以通过配置文件进行绑定,然后将此Bean归还给容器

作用于方法----->比较常见的就是配置读写分离的场景:

#数据源
spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa
spring.datasource.druid.write.username=root
spring.datasource.druid.write.password=1
spring.datasource.druid.write.driver-class-name=com.mysql.jdbc.Driver

spring.datasource.druid.read.url=jdbc:mysql://localhost:3306/jpa
spring.datasource.druid.read.username=root
spring.datasource.druid.read.password=1
spring.datasource.druid.read.driver-class-name=com.mysql.jdbc.Driver
@Configuration
public class DruidDataSourceConfig {
    
    @ConfigurationProperties(prefix = "spring.datasource.druid.read")
    @Bean(name = "readDruidDataSource")
    public DataSource readDruidDataSource() {
        return new DruidDataSource();
    }


    
    @ConfigurationProperties(prefix = "spring.datasource.druid.write")
    @Bean(name = "writeDruidDataSource")
    @Primary
    public DataSource writeDruidDataSource() {
        return new DruidDataSource();
    }
}

@Value注解,它可以通过全限定名进行配置的绑定,这里的ConfigurationProperties其实就类似于使用多个@Value同时绑定,绑定的对象就是DataSource类型的对象,而且是 隐式绑定 的,意味着在配置文件编写的时候需要与对应类的字段名称 相同,比如上述spring.datasource.druid.write.url=jdbc:mysql://localhost:3306/jpa ,当然了,你也可以随便写个配置,比如 spring.datasource.druid.write.uuu=www.baidu.com,此时你只需要在注解中加上以下参数即可

 作用于Class类及其用法 :

spring.datasource.url=jdbc:mysql://127.0.0.1:8888/test?useUnicode=false&autoReconnect=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource

@ConfigurationProperties(prefix = "spring.datasource")
@Component
public class DatasourcePro {

    private String url;

    private String username;

    private String password;

    // 配置文件中是driver-class-name, 转驼峰命名便可以绑定成
    private String driverClassName;

    private String type;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getDriverClassName() {
        return driverClassName;
    }

    public void setDriverClassName(String driverClassName) {
        this.driverClassName = driverClassName;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }
}
@Controller
@RequestMapping(value = "/config")
public class ConfigurationPropertiesController {

    @Autowired
    private DatasourcePro datasourcePro;

    @RequestMapping("/test")
    @ResponseBody
    public Map test(){

        Map map = new HashMap<>();
        map.put("url", datasourcePro.getUrl());
        map.put("userName", datasourcePro.getUsername());
        map.put("password", datasourcePro.getPassword());
        map.put("className", datasourcePro.getDriverClassName());
        map.put("type", datasourcePro.getType());

        return map;
    }
}

总结#
    @ConfigurationProperties 和 @value 有着相同的功能,但是 @ConfigurationProperties的写法更为方便@ConfigurationProperties 的 POJO类的命名比较严格,因为它必须和prefix的后缀名要一致, 不然值会绑定不上, 特殊的后缀名是“driver-class-name”这种带横杠的情况,在POJO里面的命名规则是 下划线转驼峰 就可以绑定成功,所以就是 “driverClassName”

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

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

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