Stuartd's Blog


  • 首页

  • 分类

  • 归档

JDK与JRE区别

发表于 2018-05-04 | 分类于 Java

JDK与JRE的区别与联系

含义:

JDK:Java Development Kit,简单来说就是面向开发人员用的软件开发包(Software Development Kit)

JRE:Java Runtime Enviroment,就是Java运行环境,面向Java程序的使用者,不是开发者

如果安装JDK,会同时安装两个Jre,一个在JDK所在目录中的/jre文件夹里,另一个在C:\Programe Files\Java目录下的Jre。

如果只安装Jre的话,那么就不会有JDK所在目录下的Jre,就只会有唯一一个C盘里的Jre

JRE的作用

Jre就好比于一个PC机,所有window应用程序都在PC机上运行,同样的所有的Java程序都在JRE上面运行。==Jre包含了Java虚拟机,Java基础类库等==,因此提供了运行Java的环境。

JDK的作用

JDK是提供给程序员使用的,JDK包含Jre,Javac编译器,还有很多Java程序调试和分析的工具

为什么JDK要使用两套JRE?

首先JRE是Java应用程序的运行环境,然后JDK里面的工具几乎都是Java编写的,所以也是Java应用程序,因此JDK目录下也要自附一套JRE,这是用来运行JDK里面的Java应用程序。而C盘下面的JRE是用来运行一般Java应用程序的。

还需要注意的是

  1. JVM:Java Virtual Machine。所有的Java程序都会被编译成.class文件,然后.class文件并不直接与计算机操作系统相对应,而是通过JVM与操作系统简介运行(详情看《深入分析JavaWeb技术内幕》以及《深入理解Java虚拟机》)
  2. JRE:Java Runtime Environment。光有JVM还不能成功执行.class文件,还需要一些类库lib。在安装JDK的目录下面找到JRE目录,里面有两个文件夹bin和lib,可以这样认为bin就是jvm,而lib就是jvm工作时所需要的类库,所以jre=jvm+lib,jvm=bin。==所以在写完Java程序编译成.class文件后,就可以把.class文件和jre一起打包给别人,别人就可以运行我的Java程序了(因为jre里面有运行.class文件的java.exe)==。
  3. JDK:Java Development Kit。看一下JDK的安装目录。
  • bin:最主要的编译器javac.exe
  • lib:类库
  • db:Java实现的数据库
  • include:java和JVM交互用的头文件
  • jre:JDK里面Java程序的运行环境。
  • src:src类库源码包

    真正运行Java时起作用的bin,include,lib,jre

阅读全文 »

多线程

发表于 2018-05-04 | 分类于 Java

多线程

[TOC]

继承Thread类

使用继承Thread类的方法来创建线程类时,多个线程间无法共享线程类的实例变量

步骤:

  1. 定义Thread类的子类
  2. 重写Thread类的run方法,此方法的方法体代表了线程需完成的任务
  3. 创建Thread类子类的实例,如new FirstThread()
  4. 调用实例的start()方法启动线程

由上面步骤可知,由于每次创建线程都需要创建一个新的对象,所以每个线程的实例变量不一样

实现Runable接口

使用Runable接口的方式创建的多线程可以共享线程类的实例变量

步骤:

  1. 定义Runable接口的实现类
  2. 重写Runable接口的run方法
  3. 创建Runable实现类的实例,并将此实例作为Thread的target来创建Thread对象
  4. 调用该Thread对象的start方法

由上面步骤可知,程序创建的Runable对象只是Thread的target而已,而多个线程可以共享一个target,所以多个线程可以共享同一个线程类的实例变量

使用Callable和Future创建线程

使用Callable和Future创建线程可以共享线程类的实例变量

步骤:

  1. 创建Callable接口的实现类
  2. 实现call()方法,也可以使用Lambda表达式创建Callable对象
  3. 使用FutrueTask类包装Callable对象
  4. 将FutureTask对象作为Thread对象的target启动新线程
  5. 调用FutureTask对象的get()方法获得子线程执行并结束后的返回值

由上面步骤可知,一个Callable表示一个执行体,而FutureTask是用来去除Callable里的返回值,所以当有两个FutrueTask使用同一个Callable时,这时就会出现和Runable的情况

线程运行阻塞

进入阻塞 解除阻塞
调用sleep方法 调用sleep方法超过了指定时间
调用了一个阻塞式IO方法 阻塞式IO方法已经返回
试图获取一个同步监视器 成功获取同步监视器
等待某个通知(notify) 正在等待某个通知,其他线程发出了一个通知
调用了线程的suspend方法将其挂起 线程被调用了resume方法

线程从阻塞状态只能进入就绪状态,无法直接进入运行状态

线程死亡

  • run()或call()方法完成,线程结束
  • 线程抛出一个未捕获的Exception或者Error
  • 直接调用stop()方法结束——不推荐使用,容易造成死锁

isAlive():判断是否已经死亡。(实例方法)

不要对已经死亡的线程重新start(),因为死亡就是死亡了,无法再运行了

控制线程

join()

描述:让一个线程等待另一个线程完成。当一个线程(调用者)调用了其他线程的join的方法(被join线程),调用者将被阻塞,直到被join线程执行完为止

形式:

  • join(): 等待被join线程完成
  • join(long millis): 等待被join线程完成时间为millis毫秒。若在millis毫秒内没完成,则不再等待。
  • join(long millis, int nanos): 等待被join线程的时间最长为millis毫秒加nanos毫微秒。

后台线程

描述:后台运行,为其他线程提供服务。又称“守护线程”,“精灵线程”。如JVM垃圾回收线程

特征:如果前台所有线程死亡,后台线程自动死亡。

具体操作:调用Thread对象的setDaemon(true)方法指定线程为后台线程

setDaemon(true)必须在start()方法前调用

sleep()

静态方法

描述:让当前正在执行的线程暂停一段时间,并进入阻塞状态

形式:

  • static void sleep(long millis): 暂停millis毫秒
  • static void sleep(long millis, int nanos): 暂停millis毫秒 + nanos毫微秒

yield()

静态方法

描述:让当前正在执行的线程暂停一段时间,并进入就绪状态,并等待CPU调度

具体操作:调用Thread类的yield方法

注意:当某个线程调用了yield方法暂停后,只有优先级与当前线程相同,或者优先级比当前线程更高的处于就绪状态线程才会获得执行机会

sleep和yield区别

sleep yield
暂停线程,给其他线程执行机会,不理会优先级 暂停线程,只给优先级相同或更高的线程执行机会
暂停后转入阻塞状态 强制当前线程进入就绪状态
声明抛出InterruptException异常 不声明抛出任何异常
比yield更好移植性 不建议使用yield控制并发线程执行

线程同步

synchronized

synchronized关键字可以修饰方法,可以修饰代码块,但不能修饰构造器,成员变量等

  • 使用同步代码块

语法格式:

1
2
3
synchronized(obj) {
...
}

语法格式中,synchronized后括号中的obj就是同步监视器,含义是:线程开始执行同步代码块之前,必须先获得对同步监视器的锁定

==推荐使用共享资源充当同步监视器==

  • 使用同步方法

语法格式:

1
2
3
public synchronized void Xxx() {
....
}

对于synchronized修饰的实例方法而言,没必要显式指定同步监视器,被修饰的实例方法叫做同步方法,而同步方法的同步监视器是this,也就是调用该方法的对象。

如:

1
2
3
4
5
6
7
8
9
10
11
public class Account {
public synchronized void draw() {
....
}

public void main(String[] args) {
Account account = new Account();
account.draw();
}

}

上述代码中,synchronized修饰了Account的draw这个实例方法,同时将Account这个对象当做同步监视器。原因就是因为draw是实例方法,而只有Account对象能调用draw方法,所以同步监视器就是调用draw方法的对象,即Account对象。

特征:

  • 该类的对象可以被多个线程安全地访问
  • 每个线程调用该对象的任意方法之后都将得到正确结果,原因是因为,同步监视器就是该对象
  • 每个线程调用该对象的任意方法之后,该对象状态依然保持合理状态,原因也是因为同步监视器就是该对象

由于线程安全是以降低运行效率为代价运行的,为了减少这个代价,应注意:

  • 不要对线程安全类所有方法都进行同步,即不要所有的方法都加上synchronized关键字,只对会改变竞争资源的方法进行同步。
  • 若可变类有两种运行环境:单线程和多线程,则应该为该可变类提供两种版本,即线程不安全版本和线程安全版本。单线程中使用线程不安全版本保证性能,在多线程版本中使用线程安全版本保证安全

线程通信

传统线程通信

描述:传统线程通信,可以借助Object类的wait(),notify()和notifyAll()三个方法。

wait(), notify()和notifyAll()不属于Thread类,而是Object类,而且三个方法必须由同步监视器对象调用

  • synchronized修饰的同步方法:由于同步方法的同步监视器就是该方法所在类的实例,所以可以在同步方法中直接调用
  • synchronized修饰的同步代码块:由于synchronized括号后面才是同步监视器对象,所以必须使用该对象调用

wait()

描述:是当前线程等待,直到其他线程notify或者notifyAll。

形式:

  • wait()
  • wait(long millis)
  • wait(long millis, int nanos)

notify()

描述:唤醒在此同步监视器上等待的单个线程。若所有线程都在等待,则随机唤醒一个

notifyAll()

描述:唤醒在此同步监视器上等待的所有线程

使用Lock-Condition控制线程通信

描述:若使用Lock保证同步的话,那么就得使用Condition类来保持通信

形式:Condition实例被绑定在一个Lock对象上,所以必须得通过Lock对象的newCondition方法返回一个Condition对象。

与传统线程通信对比:

传统线程通信 Lock-Condition通信
wait() await()
notify() signal()
notifyAll() signalAll()

使用BlockingQueue控制线程通信

描述:Java里有一个BlockingQueue接口,作为线程同步的工具。

特征:当生产者线程视图向BlockingQueue中放入元素时,如果该队列已满,则该生产者线程被阻塞;当消费者线程试图从BlockingQueue中取出元素时,如果队列已空,则消费者线程被阻塞

实现类:

  • ArrayBlockingQueue: 数组
  • LinkedBlockingQueue:链表
  • PriorityBlockingQueue:根据大小自然排序
  • SynchronusQueue:同步队列
  • DelayQueue:

内部方法:

抛出异常 不同返回值 阻塞线程 指定超时时长
队尾插入元素 add(e) offer(e) put(e) offer(e, time, unit)
队头删除元素 remove() poll() take() poll(time, unit)
获取但不删除元素 element() peek() 无 无

线程组

描述:Java使用ThreadGroup表示线程组,可以对一批线程进行分类管理。对线程组的控制相当于控制这一批线程。默认情况下,子线程和创建它的父线程在同一个线程组里。如main线程创建了B线程,但没有指定B线程的线程组,那么B线程则属于main线程所在的线程组

特征:一旦某个线程加入某个线程组,直到死亡,这个线程都是属于这个线程组,中途不可以改变,所以Thread类没有提供setThreadGroup()改变线程组

形式:

可以通过Thread类的构造器设置线程所属的线程组

  • Thread(ThreadGroup group, Runable target): 指定属于group线程组
  • Thread(ThreadGroup group, Runable target, String name): 指定属于group线程组,并命名name
  • Thread(ThreadGroup group, String name)

ThreadGroup构造器:

  • ThreadGroup(String name): 指定线程组名字
  • ThreadGroup(ThreadGroup parent, String name): 指定线程组名字,指定父线程组

ThreadGroup方法:

  • int activeCount(): 返回组中活动线程数目
  • interrupt(): 中断组中所有线程
  • isDaemon(): 判断此线程组是否是后台线程组
  • setDaemon(): 把线程组设置为后台线程组
  • setMaxPriority(int priority): 设置线程组最高优先级

线程池

描述:在系统启动时即创建大量空闲线程。当该线程结束任务后不是死亡,而是再次返回线程池成为空闲状态

启动:

使用Executors工厂类产生线程池

Executors静态工厂类:

  • ExecutorService newCachedThreadPool(): 具有缓存功能线程池
  • ExecutorService newFixedThreadExecutor(): 可重用,固定线程数的线程池
  • ExecutorService newSingleThreadExecutor(): 单线程线程池
  • ScheduledExecutorService newScheduledThreadPool(int corePoolSize): 创建具有指定线程数的线程池, 并且可以指定延迟
  • ScheduledExecutorService newSingleThreadScheduledExecutor(): 创建只有一个线程的线程池,可以指定延迟执行
  • ExecutorService newWorkStealingPool(int parallelism): 创建持有足够线程的线程池来支持给定的并行级别
  • ExecutorService newWorkStealingPool(): 前一个方法的简化版

如上所示,前三个返回ExecutorService,中间两个返回ScheduledExecutorService

==ExecutorService对象代表尽快执行线程的线程池==

  • Future<?> submit(Runnable task): Runnable对象提交给线程池,线程池有空时执行任务
  • Futrue submit(Runnable task, T result): 同上,其中result显式指定线程执行结束后的返回值
  • Future submit(Callable task): Callable对象交给线程池,线程池将有空时执行,其中Future代表Callable对象里call()方法的返回值

==ScheduledExecutorService对象代表在指定延迟后或周期性地执行线程任务的线程池==

  • ScheduledFuture schedule(Callable callable, long delay, TimeUnit unit): 指定callable任务在延迟delay后执行
  • ScheduleFuture<?> schedule(Runnable command, long delay, TimeUnit unit): 指定command任务在延迟delay后执行
  • ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit): 指定command任务将在delay延迟后执行,并且设定频率(period)重复执行,即在initialDelay后开始执行,依次在initialDelay+period, initialDelay+2*period, ……处重复执行
  • ScheduleFuture<?> scheduleWithFixedDelay(Runable command, long initialDelay, long delay, TimeUnit unit)

==用完一个线程池后,应调用shutdown()来关闭==

步骤:

  1. 调用Executors类的静态工厂方法创建一个ExecutorService或者ScheduledExecutorService对象,该对象代表一个线程
  2. 创建Runnable实现类或者Callable实现类实例,作为线程任务执行体
  3. 用ExecutorService或者ScheduleExecutorService对象的submit()方法提交Runnable实例或者Callable实例,这样让Runnable和Callable实例放入线程池里
  4. 不想提交任何线程时,调用ExecutorService的shutdown()方法关闭

ForkJoinPool

ForkJoinPool是ExecutorService的实现类

描述:将一个任务拆分成多个“小任务”并行计算,再把多个“小任务”的结果合并成总的计算结果。

ForkJoinPool构造器:

  • ForkJoinPool(int parallelism): 创建一个包含parallelism个并行线程的ForkJoinPool
  • ForkJoinPool(): 默认使用Runtime。availableProcessors()方法返回值作为parallelism参数创建ForkJoinPool。就是可用的处理器吧,如4核CPU,然后parallelism就是4

==重点了解一下ForkJoinTask==

ForkJoinTask是一个抽象类,其下还有两个抽象类:

  • RecursiveAction:代表有返回值的任务
  • RecursiveTask: 代表没有返回值的任务

步骤:

  1. 创建ForkJoinPool实例
  2. 调用ForkJoinPool的submit(ForkJoinTask task)或者invoke(ForkJoinTask task)方法执行指定任务。

ThreadLocal

描述:隔离多线程程序的竞争资源,又名线程局部变量

功能:为每一个使用变量的线程提供一个变量值的副本,使每一个线程可以独立改变自己副本,而不与其他线程冲突。

方法:

  • T get(): 返回当前线程中线程局部变量的值
  • void remove(): 删除当前线程中线程局部变量的值
  • void set(T value): 设置线程中线程局部变量的值

ThreadLocal与同步机制区别:

同步机制 ThreadLocal
同步机制是解决通信问题 ThreadLocal是避免多线程间对共享资源的竞争
正面解决问题 侧面避免问题

包装线程不安全集合

线程不安全集合:

  • ArrayList
  • LinkedList
  • HashSet
  • TreeSet
  • HashMap
  • TreeMap
  • …..

上述可以使用Collections的类方法包装成线程安全集合

synchronizedCollection(Collection c)
synchronizedList(List list)
synchronizedMap(Map<K, V> m)
synchronizedSet(Set s)
synchronizedSortedMap(SortedMap<K,V> m)
synchronizedSortedSet(SortedSet<K,V> m)

如

1
HashMap m = Collection.synchronizedMap(new HashMap());

线程安全集合

本知识不多做介绍,详细可以参考疯狂Java讲义 760页

  • 以Concurrent开头的集合类:代表了支持并发访问的集合
  • 以CopyOnWrite开头的集合类:略

一般使用Concurrent开头集合类,而CopyOnWrite开头的性能较差

Spring之AOP

发表于 2017-05-17 | 分类于 springboot

[TOC]

AOP(又名AspectJ)

面向切面编程,就是说解决代码复用,代码重复问题。AOP专门用于处理系统中分布于各个模块中的交叉问题

  • 下载安装
  • Eclipse导入Spring-AOP
  • AspectJ使用
  • AOP概念
  • AOP注解方式
  • AOPXML方式

下载安装

AspectJ下载与安装

  1. 地址:http://www.eclipse.org/aspectj/downloads.php
  2. 得到aspectJ-X.X.X.jar文件,然后解压,安装
  3. 安装完成后将 ==安装路径\bin== 添加到PATH环境变量中去,将==安装路径\lib\aspectjrt.jar== 添加到CLASSPATH环境变量中去

AJDT(AspectJ Develoment Tools)下载安装

  1. 这里下载:http://www.eclipse.org/ajdt/downloads/ 一定要对应eclipse的版本,比如eclipse4.3对应aspectJ版本
  2. 有两种安装方式:
    1. 第一种:把下载解压后的文件,如:ajdt_2.2.3_for_eclipse_4.3 里的features文件下的所有东西复制粘贴到eclipse的feature文件下,还有plugins这个文件一样
    2. 第二种:在eclipse中Help->Install New SoftWare->Add->选择下载好的压缩包,然后click确定,再重启eclipse就可以了
  3. 使用时,对于一般Java项目,可以右键->Configure->Convert to AspectJ 就可以了

    Eclipse XML配置Spring-AOP的命名空间

  4. (Eclipse项目包中的LIbraries)在spring.jar文件中的META—INF目录中提供了spring.schemas文件,这个文件指定了提供支持的功能的xml元素配置的命名空间定义文件的位置,在这个文件中我们可以找到aop的位置
    image
  5. 在XML文件中引入
    1
    <xmlns:aop="http://www.springframework.org/schema/aop">

之后需要在xsi:schemaLocation 中添加位置:

1
http://www.springframework.org/schema/aop(空格)http://www.springframework.org/schema/aop/spring-aop-2.5.xsd

而/spring-aop-2.5.xsd就是aop的元素的定义的文件名

AspectJ使用

在AOP中Java类仍然是普通Java,可以通过编译运行

  1. 写几个普通Java类,如

    1
    2
    3
    public class Hello(){
    ...
    }
  2. 写AspectJ,如

    1
    2
    3
    public aspect AuthAspect{

    }

==注意:aspect不用参数==

  1. 点击运行

说一下使用的背后:在已经写好的Java类中各自含有不同的方法,但现在想要在每个方法中添加一段代码,以实现某个检测功能,此时使用AspectJ切面编程能够指定在Java类中添加处理,就类似于一刀切,在每个类的Before或者After或者Around范围进行统一的处理,就不用一个一个地去添加处理代码,更好地实现了代码复用.

AOP概念

特征:

  • 各步骤间良好隔离性
  • 源代码无关性(减少了代码污染)

专业术语:

  • 切面(aspect): 组织对个处理,如:

    1
    2
    3
    public aspect HelloTest{
    //其中aspect就是指切面
    }
  • 连接点(joinpoint): 方法的调用,如:

    1
    2
    3
    4
    @Before("execution(* org.dbw.app.service.*.*(..))")
    public void authority(JoinPoint jp){
    //连接点主要作为参数,使用JoinPoint里的proceed()方法
    }
  • 增强处理(Advice): 有around,after,before等类型,如:

    1
    2
    3
    4
    5
    6
    7
    before():execution(* org.dbw.app.service.*.*(..))
    after():............
    around():...........
    //第一个* 为返回类型,如int,double等等
    //第二个* 为任意类,如Hello类,World类等等
    //第三个* 为任意方法,如foo()等等
    //括号里为参数
  • 切入点(Poincut): 可以插入增强处理(Advice)的连接点,就是说当某个连接点满足某个条件,连接点被添加进增强处理(Advice)时,该连接点编程切入点。如:

    1
    2
    poincut xxxPoincut():execution(void Org.dbw*.say*())       
    //每个方法被调用时都是连接点,如调用void dbwLove.sayLove()方法,此时为连接点(Joincut),但因为加入了增强处理,所以变成了切入点.

AOP注解

在Eclipse中添加了aop命名空间后才可以进行操作
启动@Aspect支持

1
<aop:aspectj-autoproxy/>

1. 定义切面Bean

在Spring容器中配置一个带 ==@Aspect== 注解的Bean,Spring将会自动识别该Bean,并将该Bean作为切面处理,且不会对该Bean进行增强处理(Advice)

1
2
3
4
@Asppect
public class LogAspect{
//其他内容
}

2. 定义Before增强处理

用 ==@Before== 修饰一个方法,该方法作为Before增强处理,在目标方法执行前执行所修饰的方法。通常指定一个 ==value属性值== ,该属性值指定一个切入点表达式.

1
2
3
4
5
6
7
@Aspect
public class AuthAspect{
@Before("execution(* org.dbw.app.service.*.*(..))")
public void authority(){
//其他内容
}
}

3. 定义AfterReturning增强处理

使用 ==@AfterReturn== 修饰一个方法,使其成为AfterReturn增强处理,在目标方法正常完成后执行增强处理。
常用属性:
==pointcut/value==:指定该切入点对应的切入表达式
==returning== :可获得目标方法的返回值,同时用于表示增强处理方法中可定义与这个同名的形参

1
2
3
4
5
6
7
8
9
@Aspect
public class LogAspect{
//定义一个AfterReturnning处理,returning属性指定目标方法返回值
@AfterReturning(returning="rvt",pointcut="execution(* org.dbw.app.service.*.*(..))")
//形参:形参类型会限制目标方法必须返回指定类型的值或没有返回值,与returnning属性值同名
public void log(Object rvt){
System.out.println("目标方法返回值"+ rvt);
}
}

4. 定义AfterThrowing增强处理

使用@AfterThrowing注解修饰一个方法,使其成为AfterThrowing增强处理
常用属性
==pointcut/value== 指定切入点对应的切入表达式
==throwing==:指定形参名,该形参用于访问目标方法抛出的异常

1
2
3
4
5
6
7
@Aspect
public class RepairAspect{
@AfterThrowing(throwing="ex" , pointcut="execution(* org.dbw.app.service.*.*(..))")
public void do(Throwable ex){
System.out.println("目标方法抛出的异常"+ex);
}
}

注意:AfterThrowing处理虽然可以对目标方法的异常进行处理,但这种处理与catch不同。catch捕捉是完全处理异常,而AfterThrowing处理虽然处理了异常,但不能完全处理,该异常仍然会抛给上一级调用者.

5. After增强处理

使用@After修饰一个方法,使其成为After增强处理

与AfterReturning区别: ++AfterReturning增强处理只有在目标方法成功完成后才执行++ ,++而After则不管目标方法如何结束,它都会被执行.++

1
2
3
4
5
6
7
@Aspect
public class ReleaseAspect{
@After("execution(* org.dbw.app.service.*.*(..))")
public void release(){
//其他内容
}
}

6. Around处理

使用@Around注解处理,使被修饰方法成为Around处理,近似等于Before和After总和,可以决定目标方法什么时候执行,如何执行,可以阻止目标方法执行。(详细见解看轻量级JavaEE企业应用实战P659)

用法:当定义一个Around Advice时,==第一个形参必须是ProceedingJoinPoint类型== ++(就是说至少包含一个形参)++ ,调用ProceedingJoinPoint参数的proceed()方法时,还可以传入一个Object[]对象作为参数,该数组中的值将被传入目标方法作为执行目标方法的实参。

1
2
3
4
5
6
7
8
9
10
11
12
@Aspect
public class TxAspect{
@Around("execution(* org.dbw.app.service.*.*(..))")
public Object processTx(ProceedingJoinPoint jp){
s.out.print("执行目标方法前");
//创建一个这样的数组,使其成为目标方法的形参
Object[] args = jp.getArgs();
//数组作为proceed方法形参,并用Object保留返回值
Object rvt = jp.proceed(args);
s.out.print("执行目标方法后")
}
}

Spring之高级依赖关系

发表于 2017-04-25 | 分类于 springboot

Spring之高级依赖关系

概述:

  1. 调用getter方法:使用PropertyPathFactoryBean

  2. 访问类或者对象的Field值:使用FieldRetrievingFactoryBean

  3. 调用普通方法:使用MethodInvokingFactoryBean.

  • 调用getter方法

    使用PropertyPathFactoryBean获取目标的getter方法返回值。
    ==setTargetObject(Object targetObject)== 指定使用哪个对象,调用哪个Bean
    ==setPropertyPath(String propertyPath)== 指定使用Bean的哪个getter方法
    如: 返回值作为bean
    1
    2
    3
    4
    5
    6
    <bean id="son1" class="org.springframework.beans.factory.PropertyPathFactoryBean">
    //指定使用哪个bean,这里value指定使用id为person的bean
    <property name="targetBeanName" value="person"/>
    //指定使用哪个getter方法,这里value指定使用person的bean的getAge方法
    <property name="propertyPath" value="age"/>
    </bean>

如:返回值注入另一个bean

1
2
3
4
5
<bean id="son2" class="org.dbw.app.service.Son">
<property name="age">
//person.son.age代表获取person。getSon().getAge()
<bean id="person.son.age" class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
</bean>

  • 访问类或对象的Field值

    使用FieldRetrievingFactoryBean访问类的静态Field或对象的实例Field值

==setTargetClass(String targetClass)== 指定调用哪个类
==setTargetObject(Object targetObject)== 指定使用哪个对象
==setTargetField(String targetField)== 指定访问哪个Field
==setStaticField(String staticField)== 同时指定取哪个类的哪个静态Field值

如:访问类的静态Field

1
2
3
4
<bean id="theAge1" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="targetClass" value="java.sql.Connection"/>
<property name="targetField" value="TRANSACTION SETIALIZABLE"/>
</bean>

如:访问对象的Field

1
2
3
4
<bean id="theAge2" class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<property name="targetObject" value="org.dbw.app.service.chinese"/>
<property name="targetField" value="XXXX"/>
</bean>

  • 调用普通方法

    使用MethodInvokingFactoryBean,调用任意类的类方法,也可以调用任意对象的实例方法

==setTargetObject(Object targetObject)== 指定调用哪个对象
==setTargetClass(String targetClass)== 指定调用哪个类
==setTargetMethod(String targetMethod)== 指定调用哪个方法
==setArguments(Object[] argument)== 指定方法的参数

1…34

Stuartd

不定时更新一些技术上的坑或者吐槽之类的

34 日志
11 分类
© 2019 Stuartd
|
主题 — NexT.Gemini v5.1.4
本站总访问量次