‘壹’ java动态代理是什么
import java.lang.reflect.Proxy;
A. 创建一个实现接口InvocationHandler的类,他必须实现invoke方法
B. 创建被代理的类以及接口。
C. 通过Proxy的静态方法newProxyInstance(ClassLoader loader,Class【】interfaces,InvocationHandler handler)创建一个代理
D. 通过代理调用方法。
java动态代理:是在运行是生成的class对象,在生成时必须提供一组或一个interface给它,然后该class就宣称它实现了这些interface。你当然可以把该class的实例当做这些interface中的任何一个来用,当然,这个DynamicProxy其实就是一个Proxy,他不会替你做实质性的工作,在生成它的实例时你必须提供一个handler,由它接管实际的工作。因此,DynamicProxy必须实现InvocationHandler接口。
5) 一个动态代理了和一个InvocationHandler 实现关联的。每一个动态代理实例的调用都要通过InvocationHandler接口的handler(调用处理器)来调用,动态代理不做任何执行操作,只是在创建动态代理时,把要实现的接口和handler关联,动态代理要帮助被代理执行的任务,要转交给handler来执行。其实就是调用invoke方法。
‘贰’ java动态代理和cglib动态代理的区别
1、Jdk动态代理实例:JDK动态代理只能代理实现了接口的类,其他普通类不能实现。代理类会在newProxyInstance方法中生成
2、cglib动态代理:cglib是针对类实现代理的,为代理的类生成一个子类,覆盖方法实现增强,因为采用的是继承所以不能代理final修饰的类。需要cglib和asm两个jar包
‘叁’ Java软件工程师一般要学习哪些课程
Java 是一门 c 语言,所以学习 c 语言对你学习 java 很有帮助,但是这并不意味着你不学习 c 语言就不能学习 java 仍然是相对有希望的,薪水也不错,一般本科学位可以达到2500-3000,高级程序员可以达到10000。(具体来说,客户机层是3000,表示层是5000,业务逻辑层是8000,持久层是大约10,000。)Java 的东西很零散,但是学起来并不难,只要你真的想进入这个行业。你现在只需要学习 java 的基础知识,如果你想扩展,你必须学习你在楼上谈论的东西,赚钱的主要方法是使用 javaee,它的 harbnet,spring,ejb 等等。表示层是用户在使用产品时看到的界面或页面(jsp 是 web 页面) ,业务逻辑层是用户需要添加到其中的业务逻辑(即完成用户的功能) ,持久层是持久化到数据库的所有业务逻辑。
VA是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由SUN公司推出的JAVA程序设计语言和JAVA平台的总称,JAVA应用主要由四大方向:JAVA桌面应用、WEB应用、企业级应用和嵌入式应用,具体点能干什么呢?如:Hadoop大数据处理、Android 开发、服务器开发、网站、软件开发工具、自然语言处理等等。
Java软件工程师主要学习:
首先,无论你以后从事Java的那个方向,web后台开发还是Andrio开发,那么你都需要先学习Java的基础知识。比如8种数据结构,String的常用方法,流程控制语句等基础知识。这些基础知识的学习可以去查找相关资料,也可以报课程学习。
其次,当掌握了基础知识之后,你需要学习java的进阶知识,进阶包括多线程、反射、过滤器、监听器、连接池、事务、静态代理、动态代理等相关技术。那么高级就需要学习JAVA的内存模型,虚拟机,以及Java源码等,这个阶段很多都需要根据项目实战来进行加深理解。如果是自学,很难接触到市场上真实的实战项目。
由于java应用面比较广,可以用来做行业软件、互联网软件以及大数据等软件的开发。后面要根据自己想做的方向去学习java在这个方向的主要框架,针对这些框架去学习。例如用于行业OA以及ERP的框架SSH和Spring MVC。用于互联网后台的框架SpringBoot微服务以及SpringCloud框架。大数据分Hadoop框架,自己storm的流式处理框架。
JAVA是目前全世界最广泛最实用的编程语言,JAVA本身的分类很多,如果要全部掌握,需要大量的时间。Java的发展前景目前来讲还是非常不错的,在国内的用人需求及薪资都很高。
有对Java感兴趣的同学就赶快学习起来吧,既然选择要学Java语言现在就去做,现在永远比未来早。时不等人,抓紧时间开始学习之旅吧。学习没有捷径,希望大家都能少走一些弯路,在学习Java的道路上一往无前,学有所成!
‘肆’ 什么是java代理模式,具体相关的动态代理和静态代理分别是什么举例更好啦~
简单的例子: HelloSpeaker.java
import java.util.logging.*;
public class HelloSpeaker {
private Logger logger = Logger.getLogger(this.getClass().getName());
public void hello(String name) {
logger.log(Level.INFO, "hello method starts...."); //日志记录
System.out.println("Hello, " + name); //!!!!!!!!!!!
logger.log(Level.INFO, "hello method ends...."); //日志记录
}
}
HelloSpeaker在执行hello()方法时,我们希望能记录该方法已经执行以及结束,
最简单的作法就是如上在执行的前后加上记录动作,然而Logger介入了HelloSpeaker中,
记录这个动作并不属于HelloSpeaker,这使得HelloSpeaker的职责加重。
------------------------------------------------------------------------------------------
怎么办,用下面的方法或许好一些:
先定义一个接口:
public interface IHello {
public void hello(String name);
}
------------------------------------------------------------------------------------------
实现该接口
public class HelloSpeaker implements IHello {
public void hello(String name) {
System.out.println("Hello, " + name);
}
}
public class Greeting implements IHello{
public void hello(String name){
System.out.println("Greeting, " + name);
}
}
------------------------------------------------------------------------------------------
实现一个代理对象: HelloProxy
import java.util.logging.*;
public class HelloProxy implements IHello {
private Logger logger = Logger.getLogger(this.getClass().getName());
private IHello helloObject; //被代理对象
public HelloProxy(){}
public HelloProxy(IHello helloObject) {
this.helloObject = helloObject; //把被代理对象传入
}
public void setHelloObject(IHello helloObject){
this.helloObject = helloObject;
}
public IHello getHelloObject(){
return this.helloObject;
}
public void hello(String name) {
logger.log(Level.INFO, "hello method starts...."); //日志记录
helloObject.hello(name); //!!!!!!!!调用被代理对象的方法
logger.log(Level.INFO, "hello method ends...."); //日志记录
}
}
-----------------------------------------------------------------------------------------------------
执行:
IHello helloProxy = new HelloProxy(new HelloSpeaker()); //生成代理对象, 并给它传入一个被代理的对象
helloProxy.hello("world");
//IHello h=factory.getBean("hello"); // IoC
//h.hello("world");
IHello helloProxy = new HelloProxy(new Greeting()); //生成代理对象, 并给它传入一个被代理的对象
helloProxy.hello("world");
-----------------------------------------------------------------------------------------------------
代理对象HelloProxy将代理真正的HelloSpeaker来执行hello(),并在其前后加上记录的动作,
这使得我们的HelloSpeaker在写时不必介入记录动作,HelloSpeaker可以专心于它的职责。
这是静态代理的基本范例,然而,代理对象的一个接口只服务于一种类的对象,而且如果要代理的方法很多,
我们势必要为每个方法进行代理,静态代理在程序规模稍大时就必定无法胜任.
Java在JDK 1.3之后加入协助开发动态代理功能的类,我们不必为特定对象与方法写特定的代理,使用动态代理,
可以使得一个handler服务于各个对象,首先,一个handler必须实现java.lang.reflect.InvocationHandler:
import java.util.logging.*;
import java.lang.reflect.*;
public class LogHandler implements InvocationHandler { //
private Logger logger = Logger.getLogger(this.getClass().getName());
private Object delegate; //被代理的对象
public Object bind(Object delegate) { //自定义的一个方法,用来绑定被代理对象的,返回值为被代理方法的返回值
this.delegate = delegate;
return Proxy.newProxyInstance(
delegate.getClass().getClassLoader(),
delegate.getClass().getInterfaces(),
this); //通过被代理的对象生成它的代理对象, 并同handler绑定在一起
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = null;
try {
logger.log(Level.INFO, "method starts..." + method); //日志记录
result = method.invoke(delegate, args); //!!!!!!!!调用被代理对象的方法
logger.log(Level.INFO, "method ends..." + method); //日志记录
} catch (Exception e){
logger.log(Level.INFO, e.toString());
}
return result;
}
}
InvocationHandler的invoke()方法会传入被代理对象的方法名称与参数, 实际上要执行的方法交由method.invoke(),
并在其前后加上记录动作,method.invoke()返回的对象是实际方法执行过后的回传结果。
动态代理必须有接口:
public interface IHello {
public void hello(String name);
}
实现该接口:
public class HelloSpeaker implements IHello {
public void hello(String name) {
System.out.println("Hello, " + name);
}
}
执行:
LogHandler logHandler = new LogHandler();
IHello helloProxy = (IHello) logHandler.bind(new HelloSpeaker()); //传入被代理对象, 传回代理对象
helloProxy.hello("Justin");
‘伍’ java 我不理解动态代理的意义
人家是动态编程,需要在原来的方法的功能基础上再添加一些功能,而不用改变这个方法的签名,原来调用这个方法的类依然能正常工作。
比如,现在要把一段文本发送给另一个人,普通方法是 void send(File a),现在我们弄出个特性,就像 Spring AOP 那样,在 send 之前给这个 a 压缩一下。原来的程序没有压缩功能,现在我们需要添加的话而不改变原来所有的代码的话就得用类似 AOP 这样的代码来处理。
一般一个无法再继承的类和方法,要用代理,而能够继承的类和方法可以在内在中直接生成一个新的 java 类继承它然后覆盖掉那个 send 方法,像 hibernate/spring/jboss 都把这些自动完成了。
而像 AspectJ 这种 AOP 刚不同,它直接把人家的 class 代码修改了,它就不需要使用代理。
这些在新的 JDK 6 中都可以通过 Instrument 来做到,不过也是个通用的方法,还得通过规则来定制什么情况下处理,什么时候不处理。
‘陆’ 静态代理,JDK动态代理和CGLib动态代理之前的区别
区别:
java动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP
3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
‘柒’ java中动态代理是怎么回事,和静态代理最大的区别是什么
JAVA的静态代理与动态代理比较
一、概念
代理模式是常用的Java 设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。按照代理类的创建时期,代理类可分为两种。
静态代理类:
由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了。动态代理类:在程序运行时,运用反射机制动态创建而成。
二、静态代理类
如下, HelloServiceProxy 类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl 类的相关方法来提供特定服务的。HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl 对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。
由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。
例程1 HelloService.java
package proxy;
import java.util.Date;
public interface HelloService{
public String echo(String msg);
public Date getTime();
}
例程2 HelloServiceImpl.java
package proxy;
import java.util.Date;
public class HelloServiceImpl implements HelloService{
public String echo(String msg){
return "echo:"+msg;
}
public Date getTime(){
return new Date();
}
}
例程3 HelloServiceProxy.java
package proxy;
import java.util.Date;
public class HelloServiceProxy implements HelloService{
private HelloService helloService; //表示被代理的HelloService 实例
public HelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public void setHelloServiceProxy(HelloService helloService){
this.helloService=helloService;
}
public String echo(String msg){
System.out.println("before calling echo()"); //预处理
String result=helloService.echo(msg); //调用被代理的HelloService 实例的echo()方法
System.out.println("after calling echo()"); //事后处理
return result;
}
public Date getTime(){
System.out.println("before calling getTime()"); //预处理
Date date=helloService.getTime(); //调用被代理的HelloService 实例的getTime()方法
System.out.println("after calling getTime()"); //事后处理
return date;
}
}
在Client1 类的main()方法中,先创建了一个HelloServiceImpl对象,又创建了一个HelloServiceProxy对象,最后调用HelloServiceProxy对象的echo()方法。
例程4 Client1.java
package proxy;
public class Client1{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=new HelloServiceProxy(helloService);
System.out.println(helloServiceProxy.echo("hello"));
}
}
运行Client1 类,打印结果如下:
before calling echo()
after calling echo()
echo:hello
例程3 的HelloServiceProxy 类的源代码是由程序员编写的,在程序运行前,它的.class文件就已经存在了,这种代理类称为静态代理类。
三、动态代理类
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler 接口提供了生成动态代理类的能力。
Proxy类提供了创建动态代理类及其实例的静态方法。
(1)getProxyClass()静态方法负责创建动态代理类,它的完整定义如下:
public static Class<?> getProxyClass(ClassLoader loader, Class<?>[] interfaces) throws IllegalArgumentException
参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口。
(2)newProxyInstance()静态方法负责创建动态代理类的实例,它的完整定义如下:
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler handler) throws
IllegalArgumentException
参数loader 指定动态代理类的类加载器,参数interfaces 指定动态代理类需要实现的所有接口,参数handler 指定与动态代理类关联的 InvocationHandler 对象。
以下两种方式都创建了实现Foo接口的动态代理类的实例:
/**** 方式一 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//创建动态代理类
Class proxyClass = Proxy.getProxyClass(Foo.class.getClassLoader(), new Class[] { Foo.class });
//创建动态代理类的实例
Foo foo = (Foo) proxyClass.getConstructor(new Class[] { InvocationHandler.class }).
newInstance(new Object[] { handler });
/**** 方式二 ****/
//创建InvocationHandler对象
InvocationHandler handler = new MyInvocationHandler(...);
//直接创建动态代理类的实例
Foo foo = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(),new Class[] { Foo.class }, handler);
由Proxy类的静态方法创建的动态代理类具有以下特点:
动态代理类是public、final和非抽象类型的;
动态代理类继承了java.lang.reflect.Proxy类;
动态代理类的名字以“$Proxy”开头;
动态代理类实现getProxyClass()和newProxyInstance()方法中参数interfaces指定的所有接口;
Proxy 类的isProxyClass(Class<?> cl)静态方法可用来判断参数指定的类是否为动态代理类。只有通过Proxy类创建的类才是动态代理类;
动态代理类都具有一个public 类型的构造方法,该构造方法有一个InvocationHandler 类型的参数。
由Proxy类的静态方法创建的动态代理类的实例具有以下特点:
1. 假定变量foo 是一个动态代理类的实例,并且这个动态代理类实现了Foo 接口,那么“foo instanceof Foo”的值为true。把变量foo强制转换为Foo类型是合法的:
(Foo) foo //合法
2.每个动态代理类实例都和一个InvocationHandler 实例关联。Proxy 类的getInvocationHandler(Object proxy)静态方法返回与参数proxy指定的代理类实例所关联的InvocationHandler 对象。
3.假定Foo接口有一个amethod()方法,那么当程序调用动态代理类实例foo的amethod()方法时,该方法会调用与它关联的InvocationHandler 对象的invoke()方法。
InvocationHandler 接口为方法调用接口,它声明了负责调用任意一个方法的invoke()方法:
Object invoke(Object proxy,Method method,Object[] args) throws Throwable
参数proxy指定动态代理类实例,参数method指定被调用的方法,参数args 指定向被调用方法传递的参数,invoke()方法的返回值表示被调用方法的返回值。
四、最后看一个实例:
HelloServiceProxyFactory 类的getHelloServiceProxy()静态方法负责创建实现了HelloService接口的动态代理类的实例。
例程5 HelloServiceProxyFactory.java
package proxy;
import java.lang.reflect.*;
public class HelloServiceProxyFactory {
/** 创建一个实现了HelloService 接口的动态代理类的实例
* 参数helloService 引用被代理的HelloService 实例
*/
public static HelloService getHelloServiceProxy(final HelloService helloService){
//创建一个实现了InvocationHandler接口的匿名类的实例
InvocationHandler handler=new InvocationHandler(){
public Object invoke(Object proxy,Method method,Object args[])throws Exception{
System.out.println("before calling "+method); //预处理
Object result=method.invoke(helloService,args);
//调用被代理的HelloService 实例的方法
System.out.println("after calling "+method); //事后处理
return result;
}
};
Class classType=HelloService.class;
return (HelloService)Proxy.newProxyInstance(classType.getClassLoader(),
new Class[]{classType},
handler);
}
}
如下所示的Client2 类先创建了一个HelloServiceImpl 实例,然后创建了一个动态代理类实例helloServiceProxy,最后调用动态代理类实例的echo()方法。
例程6 Client2.java
package proxy;
public class Client2{
public static void main(String args[]){
HelloService helloService=new HelloServiceImpl();
HelloService helloServiceProxy=HelloServiceProxyFactory.getHelloServiceProxy(helloService);
System.out.println("动态代理类的名字为"+helloServiceProxy.getClass().getName());
System.out.println(helloServiceProxy.echo("Hello"));
}
}
运行Client2,打印结果如下:
动态代理类的名字为$Proxy0
before calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
after calling public abstract java.lang.String proxy.HelloService.echo(java.lang.String)
echo:Hello
从结果看出,动态代理类的名字为$Proxy0。
‘捌’ Java动态代理和静态代理的区别
缺Java中的动态代理相对于静态代理优点:
1、静态代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2、静态代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。