当前位置:文档之家› java之代理

java之代理

java之代理
java之代理

Java之代理

一.概念

代理是什么呢?举个例子,一个公司是卖摄像头的,但公司不直接跟用户打交道,而是通过代理商跟用户打交道。如果:公司接口中有一个卖产品的方法,那么公司需要实现这个方法,而代理商也必须实现这个方法。如果公司卖多少钱,代理商也卖多少钱,那么代理商就赚不了钱。所以代理商在调用公司的卖方法后,加上自己的利润然后再把产品卖给客户。而客户部直接跟公司打交道,或者客户根本不知道公司的存在,然而客户最终却买到了产品。

专业点说:代理模式是对象的结构型模式,代码模式给某一个对象提供代理,并由代理对象控制原对象(目标对象,被代理对象)的引用。简单点说,就是通过一个工厂生成一个类的代理对象,当客户端使用的时候不直接使用目标对象,而是直接使用代理对象。

二.j dk的静态代理

Jdk的静态代理要求,目标对象和代理对象都要实现相同的接口。然后提供给客户端使用。这个代理对客户端是可见的,其结果图如下:

下面给出一个例子:

首先建立1个接口:UserService.java定义如下方法:

package com.xie.service;

public interface UserService {

public void addUser(String userId,String userName);

public void delUser(String userId);

public void modfiyUser(String userId,String userName);

public String findUser(String userId);

}

然后实现这个接口的目标对象:UserServiceImpl.java

package com.xie.serviceimpl;

import https://www.doczj.com/doc/ee9245245.html,erService;

public class UserServiceImpl implements UserService {

@Override

public void addUser(String userId, String userName) {

System.out.println("UserServiceImpl addUser userId->>"+userId);

}

@Override

public void delUser(String userId) {

System.out.println("UserServiceImpl delUser userId->>"+userId);

}

@Override

public void modfiyUser(String userId, String userName) { System.out.println("UserServiceImpl modfiyUser

userId->>"+userId);

}

@Override

public String findUser(String userId) {

System.out.println("UserServiceImpl findUser

userId->>"+userId);

return"张山";

}

}

为目标对象创建代理对象:UserServiceImplProxy.java代理对象持有目标对象的引用。package com.xie.serviceproxy;

import https://www.doczj.com/doc/ee9245245.html,erService;

public class UserServiceImplProxy implements UserService {

private UserService userService;

public UserServiceImplProxy(UserService userService){ https://www.doczj.com/doc/ee9245245.html,erService = userService;

}

@Override

public void addUser(String userId, String userName) { try {

System.out.println("开始执行:addUser");

userService.addUser(userId, userName);

System.out.println("addUser执行成功。");

} catch (Exception e) {

System.out.println("addUser执行失败。");

}

}

@Override

public void delUser(String userId) {

}

@Override

public void modfiyUser(String userId, String userName) {

}

@Override

public String findUser(String userId) {

return null;

}

}

最后调用代理对象完成功能:Client.java

package com.xie.client;

import https://www.doczj.com/doc/ee9245245.html,erService;

import https://www.doczj.com/doc/ee9245245.html,erServiceImpl;

import https://www.doczj.com/doc/ee9245245.html,erServiceImplProxy;

public class Client {

public static void main(String[] args) {

UserService userService = new UserServiceImplProxy(new UserServiceImpl());

userService.addUser("001", "centre");

}

}

三.j dk动态代理

静态代理要为每个目标类创建一个代理类,当需要代理的对象太多,那么代理类也变得很多。同时代理类违背了可重复代理只写一次的原则。jdk给我们提供了动态代理。其原理图如下:

Jdk的动态要求目标对象必须实现接口,因为它创建代理对象的时候是根据接口创建的。如果不实现接口,jdk无法给目标对象创建代理对象。被代理对象可以可以实现多个接口,创建代理时指定创建某个接口的代理对象就可以调用该接口定义的方法了。

首先定义2个接口:Service接口和UserService接口(上面的接口)

Service.java

package com.xie.service;

public interface Service {

public void sayHello(String name);

public int addOperter(int num,int num2);

}

然后定义实现这2个接口的目标对象:UserServiceImpl.java

package com.xie.serviceimpl;

import com.xie.service.Service;

import https://www.doczj.com/doc/ee9245245.html,erService;

public class UserServiceImpl implements UserService ,Service{

@Override

public void addUser(String userId, String userName) {

System.out.println("UserServiceImpl addUser userId->>"+userId);

}

@Override

public void delUser(String userId) {

System.out.println("UserServiceImpl delUser userId->>"+userId);

}

@Override

public void modfiyUser(String userId, String userName) {

System.out.println("UserServiceImpl modfiyUser userId->>"+userId);

}

@Override

public String findUser(String userId) {

System.out.println("UserServiceImpl findUser userId->>"+userId);

return "张山";

}

@Override

public void sayHello(String name) {

System.out.println("你好:"+name);

}

@Override

public int addOperter(int num, int num2) {

return num+num2;

}

}

提供一个生成代理对象的的类:LogHandler.java

package com.xie.serviceproxy;

import https://www.doczj.com/doc/ee9245245.html,ng.reflect.InvocationHandler;

import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Method;

import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Proxy;

public class LogHandler implements InvocationHandler {

private Object targertObject;

public Object newInstance(Object targertObject){

this.targertObject = targertObject;

Class targertClass = targertObject.getClass();

return Proxy.newProxyInstance(targertClass.getClassLoader(), targertClass.getInterfaces(),this);

}

@Override

public Object invoke(Object proxy, Method method, Object[] args)

throws Throwable {

System.out.println("调用方法"+method.getName());

Object ret = null;

try {

ret = method.invoke(targertObject, args);

System.out.print("成功调用方法:"+method.getName()+";参数为:");

for (int i = 0; i < args.length; i++) {

System.out.println(args[i]);

}

} catch (Exception e) {

e.printStackTrace();

System.out.print("调用方法:"+method.getName()+"失败;参数为:");

for (int i = 0; i < args.length; i++) {

System.out.print(args[i]);

}

}

return ret;

}

}

编写一个客户端类来使用工厂类生成目标类的代理:Client.java

package com.xie.client;

import com.xie.service.Service;

import https://www.doczj.com/doc/ee9245245.html,erService;

import https://www.doczj.com/doc/ee9245245.html,erServiceImpl;

import com.xie.serviceproxy.LogHandler;

public class Client {

public static void main(String[] args) {

Service Service = (Service)new LogHandler().newInstance(new UserServiceImpl());

UserService userService = (UserService)new LogHandler().newInstance(new UserServiceImpl());

userService.addUser("001", "centre");

String name = userService.findUser("002");

System.out.println(name);

int num = Service.addOperter(12, 23);

System.out.println(num);

Service.sayHello("centre");

}

}

四.c glib 动态代理

jdk给目标类提供动态要求目标类必须实现接口,当一个目标类不实现接口时,jdk是无法为其提供动态代理的。cglib 却能给这样的类提供动态代理。Spring在给某个类提供动态代理时会自动在jdk动态代理和cglib动态代理中动态的选择。

使用cglib为目标类提供动态代理:需要导入cglib.jar和asm.jar

如果出现asm中的类无法找到的异常,在java工程中是真的缺少asm.jar,而在web工程中很可能是asm.jar和spring提供的org.springframework.asm-3.0.4.RELEASE.jar包冲突。

首先编写一个目标类:UserServiceImpl.java(上面的类),

然后为其创建一个代理工厂,用于生成目标类的代理对象:CglibProxy.java

注意:如果一个类继承了某个类,在子类中没有一个方法,用cglib生成该子类的动态代理类中将没有一个方法。

package com.xie.serviceproxy;

import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;

import net.sf.cglib.proxy.MethodProxy;

public class CglibProxy implements MethodInterceptor{

@Override

public Object intercept(Object obj, Method method, Object[] args,

MethodProxy proxy) throws Throwable {

System.out.println("调用的方法是:" + method.getName());

Object ret = null;

try {

ret = proxy.invokeSuper(obj, args);

System.out.print("成功调用方法:"+method.getName()+";参数为:");

for (int i = 0; i < args.length; i++) {

System.out.print(args[i]);

}

} catch (Exception e) {

e.printStackTrace();

System.out.print("调用方法:"+method.getName()+"失败;参数为:");

for (int i = 0; i < args.length; i++) {

System.out.print(args[i]);

}

}

return ret;

}

}

编写一个客户端使用代理工厂生成代理对象:CglibClient.java

package com.xie.client;

import net.sf.cglib.proxy.Enhancer;

import https://www.doczj.com/doc/ee9245245.html,erServiceImpl;

import com.xie.serviceproxy.CglibProxy;

public class CglibClient {

public static void main(String[] args) {

cglibUse1();

}

public static void cglibUse1(){

Enhancer enhancer = new Enhancer();

// 设置被代理的类(目标类)

enhancer.setSuperclass(UserServiceImpl.class);

//使用回调

enhancer.setCallback(new CglibProxy());

// 创造代理(动态扩展了UserServiceImpl类)

UserServiceImpl my = (UserServiceImpl) enhancer.create();

//my.addUser("001", "centre");

int ret = my.addOperter(15, 22);

System.out.println("返回的结果是:"+ret);

}

}

五.jdk动态和cglib动态代理比较

Jdk动态代理要求被代理的类要实现接口,而cglib不需要,cglib能根据内存中为其创建子类(代理对象)。那么它们的效率是怎么样的呢?可以做如下测试:

我们用jdk和cglib动态代理分别为同一个代理创建10000个代理对象。

代码1:

public static void testFlexiable(){

UserService test = new UserServiceImpl();

long nums = 1000;

Date start = new Date();

for (int i = 0; i < nums; i++) {

UserService userService = (UserService)new

LogHandler().newInstance(test);

}

Date end = new Date();

System.out.println("创建"+nums+"个代理代理对象用时:

"+(end.getTime()-start.getTime())+"毫秒。");

}

测试结果:

创建1000个代理代理对象用时:32毫秒。

创建1000个代理代理对象用时:31毫秒。

创建1000个代理代理对象用时:31毫秒。

创建1000个代理代理对象用时:31毫秒。

创建10000个代理代理对象用时:94毫秒。

创建10000个代理代理对象用时:78毫秒。

创建10000个代理代理对象用时:78毫秒。

创建10000个代理代理对象用时:78毫秒。

代码2:

public static void testFlexiable(){

Enhancer enhancer = new Enhancer();

// 设置被代理的类(目标类)

enhancer.setSuperclass(UserServiceImpl.class);

//使用回调

enhancer.setCallback(new CglibProxy());

long nums = 1000;

Date start = new Date();

for (int i = 0; i < nums; i++) {

UserServiceImpl my = (UserServiceImpl) enhancer.create();

}

Date end = new Date();

System.out.println("创建"+nums+"个代理代理对象用时:

"+(end.getTime()-start.getTime())+"毫秒。");

}

测试结果:

创建1000个代理代理对象用时:47毫秒。

创建1000个代理代理对象用时:62毫秒。

创建1000个代理代理对象用时:62毫秒。

创建1000个代理代理对象用时:47毫秒。

创建1000个代理代理对象用时:47毫秒。

创建1000个代理代理对象用时:47毫秒。

创建10000个代理对象会抛异常,cglib运行速度明显比jdk动态代理慢,由于是通过类创建的子类,比jdk通过接口创建代理更耗内存。因此在s2sh框架中,spring通过为类提供代理采用jdk比cglib应该要好一些吧。

六.面向切面编程

面向切面编程是继面向对象后,又一种重要的思维方式。面向对象比较重要的是通过继承实现代码重用。而面向切面编程,则注重纵向编程,他能将2个不同的功能分开,实现最大程度的解耦,比如我们现在有业务逻辑层和日志层,如果不分开,那么在每个业务逻辑方法中除了要实现业务外还要加上日志代码,如果某一天我不需要日志了,而有很多这样的类的,很多方法都加上日志代码,那改动的工作量是可想而知的。有没有一种方法让我们只写一次日志代码,而把他应用在需要写日志的方法前面,当不需要的时候直接删除呢?面向切面编程给我们提供了办法。

Struts2的拦截器就是采用这种思想编写的。下面模拟实现一个拦截器,设计图如下:

首先定义一个拦截器接口:Interceptor.java

package com.xie.interceptor;

public interface Interceptor {

public void intercept(ActionInvocation invocation);

}

然后实现拦截器接口,实现3个拦截器:

FirstInterceptor.java,SecondInterceptor.java,ThirdInterceptor.java

package com.xie.interceptor;

public class FirstInterceptor implements Interceptor {

@Override

public void intercept(ActionInvocation invocation) {

System.out.println(1);

invocation.invoke();

System.out.println(-1);

}

}

package com.xie.interceptor;

public class SecInterceptor implements Interceptor {

@Override

public void intercept(ActionInvocation invocation) { System.out.println(2);

invocation.invoke();

System.out.println(-2);

}

}

package com.xie.interceptor;

public class ThirInterceptor implements Interceptor{

@Override

public void intercept(ActionInvocation invocation) { System.out.println(3);

invocation.invoke();

System.out.println(-3);

}

}

接下来定义一个InvokeInterceptory.java

package com.xie.interceptor;

import java.util.ArrayList;

import java.util.List;

public class ActionInvocation {

List interceptors=new ArrayList();

int index=-1;

Action action=new Action();

public ActionInvocation(){

this.interceptors.add(new FirstInterceptor());

this.interceptors.add(new SecInterceptor());

this.interceptors.add(new ThirInterceptor());

}

public void invoke(){

if (index+1>=this.interceptors.size()) {

action.execute();

}else {

index++;

this.interceptors.get(index).intercept(this);

}

}

}

定义一个action:Action.java

package com.xie.interceptor;

public class Action {

public void execute(){

System.out.println("execute action.");

}

}

最后定义Main类来调用action的execute方法:

package com.xie.interceptor;

public class Main {

public static void main(String[] args) {

new ActionInvocation().invoke();

}

}

运行结果如下:

1

2

3

execute action.

-3

-2

-1

在javaEE中,像Filter(过滤器),Intercepetor(拦截器),spring的事务管理都采用了面向切面的编程思想。

1.几个应用

写一个过滤器:这个过滤器的功能是实现web页面访问权限:

package com.ibeifeng.filter;

import java.io.IOException;

import javax.servlet.Filter;

import javax.servlet.FilterChain;

import javax.servlet.FilterConfig;

import javax.servlet.ServletException;

import javax.servlet.ServletRequest;

import javax.servlet.ServletResponse;

import javax.servlet.http.HttpServletRequest;

import javax.servlet.http.HttpServletResponse;

import javax.servlet.http.HttpSession;

public class LoginFilter implements Filter {

public void destroy() {

}

public void doFilter(ServletRequest req, ServletResponse res,

FilterChain chain) throws IOException, ServletException {

HttpServletRequest request = (HttpServletRequest) req;

HttpSession session = request.getSession();

String username = (String) session.getAttribute("username");

HttpServletResponse response = (HttpServletResponse) res;

String uri = request.getRequestURI();

//如果用户请求了index.html,这时就必须做登录判断,判断用户是否登录。

if("/Pfms/index.html".equals(uri)) {

if(username == null || "".equals(username)) {

response.sendRedirect("login.html");

} else {

chain.doFilter(request, response);

}

}else {

chain.doFilter(request, response);

}

}

public void init(FilterConfig filterConfig) throws ServletException {

}

}

再写一个struts2的拦截器:

package interceptor;

import com.opensymphony.xwork2.ActionInvocation;

import com.opensymphony.xwork2.interceptor.*;

import com.opensymphony.xwork2.*;

import java.util.*;

public class AuthorizationInterceptor extends AbstractInterceptor

{

private String ignoreActions;

// ignoreActions属性的getter方法

public String getIgnoreActios()

{

return ignoreActions;

}

// ignoreActions属性的setter方法

public void setIgnoreActions(String ignoreActions)

{

this.ignoreActions = ignoreActions;

}

@Override

public String intercept(ActionInvocation invocation) throws Exception {

ActionContext ctx = invocation.getInvocationContext();

Map session = ctx.getSession();

String user = (String) session.get("username");

boolean ignore = false;

String currentAction = invocation.getProxy().getActionName();

String[] actions = ignoreActions.split(",");

for (String action : actions)

{

if (currentAction.matches(action.trim()))

{

ignore = true;

break;

}

}

if (user != null || ignore == true)

{

return invocation.invoke();

}

else

{

return Action.LOGIN;

}

}

}

看看spring是如何配置事物的(xml):

class="org.springframework.orm.hibernate3.HibernateTransactionMan ager">

advice-ref="txAdvice"/>

2.面向切面的概念

1)aspect(切面):实现了cross-cutting功能,是针对切面的模块。最常见的是logging 模块,这样,程序按功能被分为好几层,如果按传统的继承的话,商业模型继承日志模块的话根本没有什么意义,而通过创建一个logging切面就可以使用AOP来实现相同的功能了。

将横切多个业务对象的程序对了出来,模块化,该模块可以无侵入式的集成到业务对象中,如:事务,日志,权限等。

2)jointpoint(连接点):连接点是切面插入应用程序的地方,该点能被方法调用,而且也会被抛出意外。连接点是应用程序提供给切面插入的地方,可以添加新的方法。比如以上我们的切点可以认为是findInfo(String)方法。

通知执行的时机,如方法调用,抛出异常时。

3)advice(处理逻辑):advice是我们切面功能的实现,它通知程序新的行为。如在logging 里,logging advice包括logging的实现代码,比如像写日志到一个文件中。advice在jointpoint 处插入到应用程序中。以上我们在MyHandler.java中实现了advice的功能。

Advice(通知):指切面的具体实现,如记录日志,验证权限。通知有各种类型,其中包括“before”,“after”,“around”和“throw”等通知

4)pointcut(切入点):pointcut可以控制你把哪些advice应用于jointpoint上去,通常你使用pointcuts通过正则表达式来把明显的名字和模式进行匹配应用。决定了那个jointpoint会获得通知。

切入点:是感兴趣的连接点。通知和一个切入点表达式关联,并在满足这个切入点上运行,(如:执行某个特定名称的方法时。)切入点表达式如何和连接点匹配时AOP的核心:spring缺省使用AspectJ切入点语法。

5)introduction:允许添加新的方法和属性到类中。

6)target(目标类):是指那些将使用advice的类,一般是指独立的那些商务模型。比如以上的StudentInfoServiceImpl.

是一个被代理对象,被通知对象,被一个或者多个切面所通知的对象。

7)proxy(代理类):使用了proxy的模式。是指应用了advice的对象,看起来和target 对象很相似。

AOP代理的对象,用来实现切面的功能,在spring中,AOP代理可以使用jdk动态代理和cglib动态代理。

8)weaving(插入):是指应用aspects到一个target对象创建proxy对象的过程:complie time,classload time,runtime。把切面连接到其它应用程序类型或者对象上,并创建一个被通知的对象,在运行时完成织入。

3.使用aspectj实现aop编程

使用aspectj编写系统日志。

Aspectj是一个使用面向切面,底层采用动态代理的框架。AspectJ是一个面向切面的框架,它扩展了Java语言。AspectJ定义了AOP语法所以它有一个专门的编译器用来生成遵守Java 字节编码规范的Class文件。spring的AOP实现使用了Aspectj框架。

1.采用annotation

a)首先开启aspectj支持,如下:

xmlns="https://www.doczj.com/doc/ee9245245.html,/schema/beans"

xmlns:xsi="https://www.doczj.com/doc/ee9245245.html,/2001/XMLSchema-instance"

xmlns:context="https://www.doczj.com/doc/ee9245245.html,/schema/context"

xmlns:aop="https://www.doczj.com/doc/ee9245245.html,/schema/aop"

xmlns:tx="https://www.doczj.com/doc/ee9245245.html,/schema/tx"

xsi:schemaLocation="

https://www.doczj.com/doc/ee9245245.html,/schema/beans

https://www.doczj.com/doc/ee9245245.html,/schema/beans/spring-beans-3.0.xsd

https://www.doczj.com/doc/ee9245245.html,/schema/context

https://www.doczj.com/doc/ee9245245.html,/schema/context/spring-context-3.0.xsd https://www.doczj.com/doc/ee9245245.html,/schema/tx

https://www.doczj.com/doc/ee9245245.html,/schema/tx/spring-tx-3.0.xsd https://www.doczj.com/doc/ee9245245.html,/schema/aop

https://www.doczj.com/doc/ee9245245.html,/schema/aop/spring-aop-3.0.xsd">

如果采用dtd:

b)定义切面对象

@Aspect

c)申明切入点

任何public方法的执行:

execution(public * *(..))

任何以set开头的方法:

execution(* set*(..))

任何在接口AccountService的方法:

execution(* com.xyz.service.AccountService.*(..))

任何在service包的方法:

execution(* com.xyz.service.*.*(..))

任何在service包和其子包的方法:

execution(* com.xyz.service..*.*(..))

any join point (执行方法必须在Spring Aop方式下) within the service package:

within(com.xyz.service.*)

any join point (执行方法必须在Spring Aop方式下) within the service package or a sub-package:

within(com.xyz.service..*)

any join point (执行方法必须在Spring Aop方式下) where the proxy implements the AccountService interface:

this(com.xyz.service.AccountService)

any join point (method execution only in Spring AOP) where the target object implements the AccountService interface:

target(com.xyz.service.AccountService)

'target' is more commonly used in a binding form :- see the following section on advice for how to make the target object available in the advice body.

any join point (method execution only in Spring AOP) which takes a single parameter, and where the argument passed at runtime is Serializable:

args(java.io.Serializable)

'args' is more commonly used in a binding form :- see the following section on advice for how to make the method arguments available in the advice body.

any join point (method execution only in Spring AOP) where the target object has an @Transactional annotation:

@target(org.springframework.transaction.annotation.Transactional)

'@target' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

any join point (method execution only in Spring AOP) where the declared type of the target object has an @Transactional annotation:

@within(org.springframework.transaction.annotation.Transactional)

'@within' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

any join point (method execution only in Spring AOP) where the executing method has an @Transactional annotation:

@annotation(org.springframework.transaction.annotation.Transactional)

'@annotation' can also be used in a binding form :- see the following section on advice for how to make the annotation object available in the advice body.

any join point (method execution only in Spring AOP) which takes a single parameter, and where the runtime type of the argument passed has the @Classified annotation:

@args(com.xyz.security.Classified)

'@args' can also be used in a binding form :- see the following section on advice for how to make the annotation object(s) available in the advice body.

any join point (method execution only in Spring AOP) on a Spring bean named 'tradeService':

bean(tradeService)

any join point (method execution only in Spring AOP) on Spring beans having names that match the wildcard expression '*Service':

bean(*Service)

d)切入点表达式:

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?

name-pattern(param-pattern) throws-pattern?)

--modifiers-pattern 访问修饰符,public,private等

-- ret-type-pattern 返回类型,void,String等

-- declaring-type-pattern 申明类型

-- name-pattern 方法名称

-- param-pattern 参数名称

-- throws-pattern 异常名称

编写一个接口:ServiceAspectjAnnotation.java

package com.xie.aspectj.test;

import java.util.List;

import com.hikvision.webclient8100.domain.Depart;

public interface ServiceAspectjAnnotation {

public boolean delete(List list);

public boolean change(List list);

public List queryAll();

public Depart queryBySequenceNo(String sequenceNo);

public String pageDivide(int index, int pageSize);

public String findParentOrgsName() throws Exception;

boolean save(List list);

}

实现该接口:ServiceAspectjAnnotationImpl.java

package com.xie.aspectj.test;

import java.util.List;

import https://www.doczj.com/doc/ee9245245.html,ponent;

import com.hikvision.webclient8100.domain.Depart;

@Component(value="serviceAspectjAnnotationImpl")

public class ServiceAspectjAnnotationImpl //implements ServiceAspectjAnnotation

{

public boolean save(List list) {

System.out.println("保存方法执行成功。");

return false;

}

public boolean delete(List list) {

System.out.println("删除方法执行成功。");

return false;

}

public boolean change(List list) {

System.out.println("修改方法执行成功。");

return false;

}

public List queryAll() {

System.out.println("查询成功。");

return null;

}

设计模式优缺点及应用场景整理

看完发现有不太对的地方告诉我下 各设计模式优缺点总结 1桥接模式 优点:1 将实现予以解耦,让它和界面之间不再永久绑定 2 抽象和实现可以独立扩展,不会影响到对方 3 对于“具体的抽象类”所做的改变,不会影响到客户。 缺点:1. 增加了复杂度 用途:1. 适合使用在需要跨越多个平台的图形和窗口上 2. 当需要用不同的方式改变接口和实现时,你会发现桥接模式很好用。 具体实例:跨平台的软件,不同电视机和不同的遥控器。 2生成器模式(建造者模式) 优点: 1.将一个复杂对象的创建过程封装起来 2.允许对象通过多个步骤来创建,并且可以改变创建过程 3.向客户隐藏内部的表现 4.产品的实现可以被替换,因为客户只看到一个抽象的接口 缺点: 1.与工厂模式相比,采用生成器模式创建对象更复杂,其客户,需要更多的知识领域。用处: 用来创建组合结构。 典型例子: 想不起典型例子 还是扯那个画小人,构建小人分画头,画身体,画双手,黄双脚等不同构建部分,全部放在一起构建。 3职责链模式 优点: 1.将请求的发送者和接收者解耦 2.可以简化你的对象,因为它不需要知道链的结构 3.通过改变链内的成员或调动他们的次序,允许你动态地新增或删除责任 缺点: 1.并不保证请求一定会被执行,如果没有任何对象处理它的话,它可能会落到链尾端 之外 2.可能不容观察运行时的特征,有碍于除错。 用途:

经常被使用在窗口系统中,处理鼠标和键盘之类的事件。 当算法牵涉到一种链型运算,而且不希望处理过程中有过多的循环和条件选择语句,并且希望比较容易的扩充文法,可以采用职责链模式。 1)有多个对象处理请求,到底怎么处理在运行时确定。 2)希望在不明确指定接收者的情况下,向多个对象中的一个提交请求。 3)可处理一个请求的对象集合应该被动态指定。 典型例子: 一个请求发送给前台,前台表示我无权管理,将请求传递给财务部门,财务部门再……4蝇量模式(享元) 优点: 1.减少运行时对象实例的个数,节省内存 2.将许多“虚拟”对象的状态集中管理 缺点: 一旦你实现了它,单个的逻辑实现将无法拥有独立而不同的行为 用途: 当一个类有许多的实例,而这些实例能被同一方法控制的时候,我们就可以使用蝇量模式。(这话什么意思啊,HF书上原话,是这话有问题还是我理解能力有问题?!) 具体场景: 五子棋中的黑白子,改变坐标状态(x,y),但用同一个实体。 5解释器模式(这个模式我真没仔细看) 优点: 1.将每一个语法规则表示成一个类,方便事先语言。 2.因为语法由许多类表示,所以你可以轻易地改变或扩展此语言 3.通过在类结构中加入新的方法,可以在解释的同时增加新的行为,例如打印格式的梅花或者进行复制的程序验证。 缺点: 当语法规则数目太大时,这个模式可能会变得非常繁琐。 用途: 1.当你需要实现一个简答的语言时,使用解释器 2.当你有一个简单的语法,切简单比效率更重要时,使用解释器 3.可以处理脚本语言和编程语言 典型例子:正则表达式 6中介者模式 优点: 1.通过将对象彼此解耦,可以增加对象的复用性。 2.通过将控制逻辑集中,可以简化系统维护

动态代理

动态代理 简单介绍 代理可分为静态代理和动态代理。静态代理在源代码级实现,而动态代理在运行时实现。 代理的几个概念: 抽象角色:声明真实对象和代理对象的共同接口。(就是接口) 代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代理对象可以在执行真实对象操作时,附加其他的操作,相当于对真实对象进行封装。(就是实现上述接口的代理,即代理对象)真实角色:代理角色所代表的真实对象,是我们最终要引用的对象。(就是要代理的真正对象,即被代理对象,或称目标对象) 在使用JDK中的动态代理时,要注意目标对象必须实现接口。动态代理的几个概念: 动态代理类:实现了一系列的接口,而这些接口是在动态代理类被创建时指定的。 代理接口:就是由动态代理类所实现的接口。 代理实例:就是动态代理类的实例。 动态代理类和其实例可以由https://www.doczj.com/doc/ee9245245.html,ng.reflect.Proxy来创建。如要创造接口Foo的代理: InvocationHandler handler = new MyInvocationHandler(...); //创建动态代理类 Class proxyClass = Proxy.getProxyClass( Foo.class.getClassLoader(), new Class[] { Foo.class }); //创建动态代理类的实例 Foo f = (Foo) proxyClass. getConstructor(new Class[] { InvocationHandler.class }). newInstance(new Object[] { handler }); 或者使用(更简单,一步完成创建动态代理类的实现): Foo f = (Foo) Proxy.newProxyInstance(Foo.class.getClassLoader(), new Class[] { Foo.class }, handler); 实例演示 DynamicProxy.java

Java分布式架构设计

Java分布式架构设计 一种互联网应用的分布式架构模式微服务应用框架的实现(gradle,dubbo,zookeeper,springmmvc) 简介: 框架是用freemarker、springmvc、dubbo、hibernate编写的快速互联网应用敏捷开发框架,采用web层和service层分离独立的设计模式, 用最流行的微服务架构,使用gradle替代maven管理项目结构依赖 架构应用图: 主要分5部分组成: fw_core:核心微层服务基类 fw_web:前端web框架使用 fw_facade:api层记录 fw_string:字符串处理 fw_cg:代码生成工具 此项目已经放到github上,由于时间有限,开档不全!

希望各位大神有好的建议,联系我一起交流! 源码地址:https://https://www.doczj.com/doc/ee9245245.html,/ligson/hfw (技术交流扣扣群:487490324) 微服务架构的好处 微服务架构模式有很多好处。首先,通过分解巨大单体式应用为多个服务方法解决了复杂性问题。在功能不变的情况下,应用被分解为多个可管理的分支或服务。每个服务都有一个用RPC-或者消息驱动API定义清楚的边界。微服务架构模式给采用单体式编码方式很难实现的功能提供了模块化的解决方案,由此,单个服务很容易开发、理解和维护。 第二,这种架构使得每个服务都可以有专门开发团队来开发。开发者可以自由选择开发技术,提供API服务。当然,许多公司试图避免混乱,只提供某些技术选择。然后,这种自由意味着开发者不需要被迫使用某项目开始时采用的过时技术,他们可以选择现在的技术。甚至于,因为服务都是相对简单,即使用现在技术重写以前代码也不是很困难的事情。 第三,微服务架构模式是每个微服务独立的部署。开发者不再需要协调其它服务部署对本服务的影响。这种改变可以加快部署速度。UI团队可以采用AB测试,快速的部署变化。微服务架构模式使得持续化部署成为可能。 最后,微服务架构模式使得每个服务独立扩展。你可以根据每个服务的规模来部署满足需求的规模。甚至于,你可以使用更适合于服务资源需求的硬件。比如,你可以在EC2 Compute Optimized instances上部署CPU敏感的服务,而在EC2 memory-optimized instances上部署内存数据库。 微服务架构的不足 Fred Brooks在30Year前写道,“there are no silver bullets”,像任何其它科技一样,微服务架构也有不足。其中一个跟他的名字类似,『微服务』强调了服务大小,实际上,有一些开发者鼓吹建立稍微大一些的,10-100 LOC服务组。尽管小服务更乐于被采用,但是不要忘了这只是终端的选择而不是最终的目的。微服务的目的是有效的拆分应用,实现敏捷开发和部署。 另外一个主要的不足是,微服务应用是分布式系统,由此会带来固有的复杂性。开发者需要在RPC或者消息传递之间选择并完成进程间通讯机制。更甚于,他们必须写代码来处理消息传递中速度过慢或者不可用等局部失效问题。当然这并不是什么难事,但相对于单体式应用中通过语言层级的方法或者进程调用,微服务下这种技术显得更复杂一些。 另外一个关于微服务的挑战来自于分区的数据库架构。商业交易中同时给多个业务分主体更新消息很普遍。这种交易对于单体式应用来说很容易,因为只有一个数据库。在微服务架构应用中,需要更新不同服务所使用的不同的数据库。使用分布式交易并不一定是好的选择,不仅仅是因为CAP理论,还因为今天高扩展性的NoSQL数据库和消息传递中间件并不支持这一需求。最终你不得不使用一个最终一致性的方法,从而对开发者提出了更高的要求和挑战。

java核心技术试题

下列能自动为上下文中定义的所有的Bean生成代理的类为:() A. ProxyFactoryBean B. BeanNameAutoProxyCreator C. DefaultAdvisorAutoProxyCreator 若Hibernate的Session出现了Spring中的HibernateTemplate中没有的方法,则:( ) A. 无法使用Spring的HibernateTemplate了 B. 可以使用HibernateTemplate的回调方法 以下程序的打印结果是什么:( ) 1) tx = session.beginTransaction(); 2) Customer c1=(Customer)session.load(Customer.class,new Long(1)); 3) Customer c2=(Customer)session.load(Customer.class,new Long(1)); 4) System.out.println(c1==c2); 5) https://www.doczj.com/doc/ee9245245.html,mit(); 6) session.close(); A. 运行出错,抛出异常 B. 打印false C. 打印true 以下程序代码对Customer的name属性修改了两次 1) tx = session.beginTransaction(); 2) Customer customer=(Customer)session.load(Customer.class,new Long(1)); 3) customer.setName("Jack"); 4) customer.setName("Mike"); 5) https://www.doczj.com/doc/ee9245245.html,mit(); 执行以上程序,Hibernate需要向数据库提交几条update语句:( ) A.0 B. 1 C. 2 D. 3 以下哪一种检索策略利用了外连结查询:( ) A. 立即检索 B. 延迟检索 C. 迫切左外连结检索 假设对Customer类的orders集合采用延迟检索策略,编译或运行以下程序,会出现什么情况:( ) 1) Session session=sessionFactory.openSession(); 2) tx = session.beginTransaction(); 3) Customer customer=(Customer)session.get(Customer.class,new Long(1)); 4) https://www.doczj.com/doc/ee9245245.html,mit(); 5) session.close(); 6) Iterator orderIterator=customer.getOrders().iterator(); A. 编译出错 B. 编译通过,并正常运行 C. 编译通过,但运行时抛出异常 如果让数据库中的表与POJO对应,我们必须通过:( )映射 A. *.class B. *.xml C. *.hbm.xml; D. *.java 我们在实用Set方式映射一对多单向关联时,下列那句话是正确的:( )

JAVA的反射机制与动态代理

JA V A的反射机制与动态代理 李海峰(QQ:61673110)-Andrew830314@https://www.doczj.com/doc/ee9245245.html, 运行时类型信息(RunTime Type Information,RTTI)使得你在程序运行时发现和使用类型信息。RTTI主要用来运行时获取向上转型之后的对象到底是什么具体的类型。 1.Class对象: JAVA使用Class对象来执行RTTI。每个类都有一个Class对象,它用来创建这个类的所有对象,反过来说,每个类的所有对象都会关联同一个Class对象(对于数组来说,维数、类型一致的数组的Class对象才是相同的),每个对象的创建都依赖于Class对象的是否创建,Class对象的创建发生在类加载(https://www.doczj.com/doc/ee9245245.html,ng.ClassLoader)的时候。 https://www.doczj.com/doc/ee9245245.html,ng.Class类实现了Serializable、GenericDeclaration、Type、AnnotatedElement四个接口,分别实现了可序列化、泛型定义、类型、元数据(注解)的功能。 你可以把Class对象理解为一个类在内存中的接口代理(它代理了这个类的类型信息、方法签名、属性),JVM加载一个类的时候首先创建Class对象,然后创建这个类的每个实例的时候都使用这个Class对象。 Class只有一个私有的无参构造方法,也就是说Class的对象创建只有JVM可以完成。 如何验证同一个类的多个对象的Class对象是一个呢? Cf1 cf1 = new Cf1(); Class clazz = Cf1.class; System.out.println(cf1.getClass() == clazz); 我们知道==用来比较引用是否相等(也就是同一个引用),上面的输出语句结果是true。那么Class对象是否相等是JAVA对象中唯一可以使用==判断的。 如何获取Class对象: 1.所有的引用数据类型(类-类型)的类名、基本数据类型都可以通过.class方式获取其Class 对象(对于基本数据类型的封装类还可以通过.TYPE的方式获取其Class对象,但要注意.TYPE实际上获取的封装类对应的基本类型的Class对象的引用,那么你可以判断出int.class==Integer.TYPE返回true,int.class==Integer.class返回false!),通过这种方式不会初始化静态域,使用.class、.TYPE的方式获取Class对象叫做类的字面常量; 2.Class的forName(String name)传入一个类的完整类路径也可以获得Class对象,但由于使用的是字符串,必须强制转换才可以获取泛型的Class的Class对象,并且你必须获取这个方法可能抛出的ClassNotFoundException异常。 2.对于引用数据类的引用(必须初始化),可以通过Object类继承的getClass()方法获取这个引用的Class对象,由于引用已经被初始化,所以这种方式也不会初始化静态域,因为静态域已经被初始化过。另外,前面两种方式如果说是创建Class对象,那么这种方式应该是取得Class对象,因为类的实例已经被创建,那么Class对象也一定早就被创建。 Class的常用方法: l forName(String name):这是一个静态方法,传入的参数是一个类的完整类路径的字符串,返回这个类的Class对象,前面说过Class对象的创建发生在类的加载时,所以这个方法会导致静态成员被调用; l forName(String name,boolean initialize,ClassLoader loader):这是上面的方

设计模式试验--代理模式、命令模式

浙江工商大学计算机与信息工程学院 学期上机实验报告 课程名称:设计模式姓名:学号: 指导教师:班级:日期: 【一】实验目的: (1)掌握代理模式的意图、使用方法和优缺点。 (2)掌握命令模式的意图、使用方法和优缺点。 【二】实验内容: (1) 设计一个智能引用代理,用来计算应用程序中ImageIcon对象被引用的次数。其中ImageIcon 属于java.swing包,从Icon类继承而来。 (2) 某应用程序需要添加图形(用Graphics类)和文档(用Document),如图1所示。现要求用命令模式重新设计,以实现添加图形和文档的重复操作和撤消操作,并写出程序框架。 图1

【三】完成报告(预备知识、步骤、程序框图、程序、思考等):第一题 UML类图: Java代码: IIcon.java /** * @author **** * */ public interface IIcon { public void paint(); }

ImageIconReal.java import java.swing.*; /** * @author **** * */ public class ImageIconReal implements IIcon { public void paint(){ System.out.println("引用ImageIcon对象"); } } ImageIconProxy.java /** * @author **** * */ public class ImageIconProxy implements IIcon { private IIcon iicon; public ImageIconProxy (IIcon iicon){ this.iicon = iicon; } public void paint(){

泛型动态代理基础

泛型(Generic) —泛形的作用 JDK5中的泛形允许程序员在编写集合代码时,就限制集合的处理类型,从而把原来程序运行时可能发生问题,转变为编译时的问题,以此提高程序的可读性和稳定性(尤其在大型程序中更为突出)。 注意:泛型是提供给javac编译器使用的,它用于限定集合的输入类型,让编译器在源代码级别上,即挡住向集合中插入非法数据。但编译器编译完带有泛形的java程序后,生成的class文件中将不再带有泛形信息,以此使程序运行效率不受到影响,这个过程称之为“擦除”。 泛形的基本术语,以ArrayList为例:<>念着typeof ArrayList中的E称为类型参数变量 ArrayList中的Integer称为实际类型参数 整个称为ArrayList泛型类型 整个BaseDaoParameterizedType/Type 自定义泛形——泛型类和反射泛形 如果一个类多处都要用到同一个泛型,这时可以把泛形定义在类上(即类级别的泛型),语法格式如下: public class GenericDao { private T field1; public void save(T obj){} public T getId(int id){} } 泛形的典型应用:BaseDao和反射泛型 Annotation(注解) 概述 从JDK 5.0 开始, Java 增加了对元数据(MetaData) 的支持, 也就是Annotation(注解)。 什么是Annotation,以及注解的作用?三个基本的Annotation: @Override: 限定重写父类方法, 该注解只能用于方法 @Deprecated: 用于表示某个程序元素(类, 方法等)已过时 @SuppressWarnings: 抑制编译器警告. Annotation 其实就是代码里的特殊标记, 它用于替代配置文件,也就是说,传统方式通过配置文件告诉类如何运行,有了注解技术后,开发人员可以通过注解告诉类如何运行。在Java 技术里注解的典型应用是:可以通过反射技术去得到类里面的注解,以决定怎么去运行类。掌握注解技术的要点: 如何自定义注解 如何反射注解,并根据反射的注解信息,决定如何去运行类

代理模式

【代理模式应用场景举例 代理模式应用场景举例】 代理模式应用场景举例 比如在玩“极品飞车”这款游戏, 如果游戏者手中的金钱达到了一定的数量就可以到车 店买一部性能更高的赛车,那么这个卖车的“车店”就是一个典型的“汽车厂家”的“代 理”,他为汽车厂家“提供卖车的服务”给有需求的人士。从面向对象的方面考虑,“销售 汽车的代理”也是一个对象, 那么这个对象也具有一定的状态, 在软件项目中这个对象也具 有管理财务进销存的基本功能, 那么在设计时就要以面向 OOP 编程的思想来考虑软件的类结 构,这个销售汽车的代理也是一个类了。 【代理模式解释】 代理模式解释】 类型:结构模式 对一些对象提供代理,以限制那些对象去访问其它对象。 【代理模式 UML 图】 代理模式 【代理模式-JAVA 代码实现 代理模式代码实现】 代理模式 新建一个买车的接口:
package buy_car_package;public interface buy_car_package { public void buy_car(); }
新建一个 people 人类,具有买车的行为,所以实现接口 buy_car_package:
package buy_car_imple; import buy_car_package.buy_car_package;public class people implements buy_car_package { private int cash; private String username; public int getCash() { return cash; }

尚硅谷_动态代理

————————————————————————————— 动态代理原理简析 一、概述 1.动态编译https://www.doczj.com/doc/ee9245245.html,pilationTask 动态编译想理解自己查API文档 2.反射被代理类主要使用Method.invoke(Object o,Object... args);对带有指定参数的指定对象调用由此Method 对象表示的底层方法。 3.类的加载URLClassLoader可以加载硬盘任意位置的.java文件。class.getClassLoader只能加载classPath目录下的类。 动态代理可以理解为动态生成发射代理的类。这其中可以动态增加逻辑操作。比如日志的打印,事物的处理等。spring的AOP操作也是动态代理的。 二、创建业务接口 假设我们有一个接口GrowAble可成长的。 1.package https://www.doczj.com/doc/ee9245245.html,; 2. 3.public interface GrowAble { 4. void growUp(); 5.} 一棵小树苗实现了这个接口 1.package https://www.doczj.com/doc/ee9245245.html,; 2.public class Tree implements GrowAble { 3. @Override 4. public void growUp() { 5. System.out.println('I am a tree , I'm grow up!'); 6. } 7. 8.} 这时我们想不在不改变源码的情况下想知道树长了多少这个操作? 我们需要一个转换接口。

————————————————————————————— 1.package https://www.doczj.com/doc/ee9245245.html,; 2.import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Method; 3. 4.public interface InvactionHandle { 5. void invoke(Object o,Method m); 6.} 一个实现接口类。 01.package https://www.doczj.com/doc/ee9245245.html,; 02.import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Method; 03.import java.util.Random; 04. 05.public class HeightInvactionHandle implements InvactionHandle { 06. @Override 07. public void invoke(Object c, Method m) { 08. try { 09. m.invoke(this.o); 10. System.out.println('这棵树长了' + new Random().nextInt(9527)+'米!!!' ); 11. } catch (Exception e) { 12. e.printStackTrace(); 13. } 14. } 15. private Object o; 16. public HeightInvactionHandle(Object o) { 17. super(); 18. this.o = o; 19. } 20.} 三、其他重要类 现在最重要的Proxy类了。把上述两个接口接口起来。 01.package https://www.doczj.com/doc/ee9245245.html,;

阿里巴巴编码规范(Java)题库

多选1.如何处理单元测试产生的数据,下列哪些说法是正确的?ABC A .测试数据入库时加特殊前缀标识。 B .测试数据使用独立的测试库。 C .自动回滚单元测试产生的脏数据。 D .无须区别,统一在业务代码中进行判断和识别。 多选2.关于并发处理,下列哪些说法符合《阿里巴巴Java开发手册》:ABC A .线程资源必须通过线程池提供,不允许在应用中自行显式创建线程。 B .同步处理时,能锁部分代码区块的情况下不要锁整个方法;高并发时,同步调用应该考虑到性能损耗。 C .创建线程或线程池时,推荐给线程指定一个有意义的名称,方便出错时回溯。 D .推荐使用Executors.newFixedThreadPool(int x)生成指定大小的线程池。(线程池不允许使用Executors 去创建,而是通过ThreadPoolExecutor 的方式) 多选3.下列哪些说法符合《阿里巴巴Java开发手册》:ACD A .对于“明确停止使用的代码和配置”,如方法、变量、类、配置文件、动态配置属性等要坚决从程序中清理出去,避免造成过多垃圾。 B .永久弃用的代码段注释掉即可,即不用加任何注释。 C .对于暂时被注释掉,后续可能恢复使用的代码片断,在注释代码上方,统一规定使用三个斜杠(///)来说明注释掉代码的理由。 D .不要在视图模板中加入任何复杂的逻辑。 多选4.关于分页查询,下列哪些说法符合《阿里巴巴Java开发手册》:ABC A .分页查询,当统计的count为0时,应该直接返回,不要再执行分页查询语句。 B .iBATIS自带的queryForList(String statementName,int start,int size)分页接口有性能隐患,不允许使用。 C .定义明确的sql查询语句,通过传入参数start和size来实现分页逻辑。 D .可使用存储过程写分页逻辑,提高效率。

proxy-动态代理深度学习

一.相关类及其方法: https://www.doczj.com/doc/ee9245245.html,ng.reflect.Proxy, Proxy 提供用于创建动态代理类和实例的静态方法. newProxyInstance() 返回一个指定接口的代理类实例,该接口可以将方法调用指派到指定的调用处理程序 (详见api文档) https://www.doczj.com/doc/ee9245245.html,ng.reflect.InvocationHandler, InvocationHandler 是代理实例的调用处理程序实现的接口。 invoke() 在代理实例上处理方法调用并返回结果。在与方法关联的代理实例上调用方法时,将在调用处理程序上调用此方法。 (详见api文档) 二.源代码: 被代理对象的接口及实现类: package com.ml.test; public interface Manager { public void modify(); } package com.ml.test; public class ManagerImpl implements Manager { @Override public void modify() {

System.out.println("*******modify()方法被调用"); } } 业务代理类: package com.ml.test; import https://www.doczj.com/doc/ee9245245.html,ng.reflect.InvocationHandler; import https://www.doczj.com/doc/ee9245245.html,ng.reflect.Method; public class BusinessHandler implements InvocationHandler { private Object object = null; public BusinessHandler(Object object) { this.object = object; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("do something before method"); Object ret = method.invoke(this.object, args); System.out.println("do something after method"); return ret; } }

java动态代理实现Authorization(授权)

动态代理实现Authorization(授权) * https://www.doczj.com/doc/ee9245245.html,ng.reflect包中的 Proxy和InvocationHandler接口提供了创建(指定类[接口更准确些]的)动态代理类的能力。 我们知道,对象是类的实例,一般使用内存来模拟对象,对象是依据类为模板来创建的,创建时使用new来分配一块内存区(其布局 参考相应类的内存布局),为变量做一些赋值便是对象的初始化了。我们知道通常类是设计时的产物,在设计时我们编写对象的模板(即——类),运行时 产生类的实例。类所处的文件是 .java文件——源文件,之后编译为jvm-----java虚拟机可解释执行的.class字节码文件,在类解析 过程中这些.class文件由类加载器加载到虚拟机(可实现自己的类加载器来加载处于特定路径下的类,或加载用某种加密算法加密过的类文件---这样 便于进行安全控制——具体描述参考(Core java ——Java核心卷二))。在遇到创建对象的指令时使用加载的类来创建对象内存 空间。动态代理是不用创建类文件(当然也不用创建java源文件),就能在虚拟机中构造出类文件区域来(相当于使用Proxy类来 创建一块类内存区域,该区域中的内容相当于加载某个.class文件产生的区域;比如我们在使用DOM技术时,从一个XML文件构造一个 DOM内存表示,它是XML文件的内存表示,但我们也可以直接使用DOM API在内存中构建一个dom树,最终结果就是一个内存DOM树,你不用关心 这个dom树是来自于xmL文件还是直接的运行时构造)。 * ** 关于代理设计模式,这里不再敷述。代理和被代理类(目标类)实现共同的接口。我们在调用时不需区别它是否是真正的目标对象。 代理会转发请求到目标对象的。比如互联网上的代理服务器,我们不必关心它是不是代理,就当它不存在一样。对客户调用端 他是不关心具体是谁来提供这个服务功能;在服务端选择使用代理的原因可能是:安全,日志,防火墙等。就是说代理可提供一些 非功能性功能,比如缓存功能____来加速服务的响应的速度。在面向方面技术(AOP)中这些非功能性需求被称作“方面”他们横切于功能类 的实现中,比如:某个SubServerImpl(子服务实现)中的某个服务方法: subServer.doService(){ //在日志输出中常有类似的代码出现于多个类实现中 loger.log(""); } 如果已经存在了一个服务实现,你还需要加入日志功能,而又不想改动既有的实现,也不想太多的改动客户端,我们可以引入

Java反射机制与动态代理

前言,在Java运行时刻,能否知道一个类的属性方法并调用改动之?对于任意一个对象,能否知道他的所属类,并调用他的方法?答案是肯定的。这种动态的获取信息及动态调用方法的机制在Java中称为“反射”(reflection)。 Java反射机制主要提供以下功能: 在运行时判断任意一个对象所属的类; 在运行时构造任意一个类的对象; 在运行时判断任意一个类所具有的成员变量和方法; 在运行时调用任意一个对象的方法。 Reflection 是Java被视为动态(或准动态)语言的一个关键性质。这个机制允许程序在运行时透过Reflection APIs取得任何一个已知名称的class的内部信息,包括其modifiers(诸如public, static 等等)、superclass(例如Object)、实现之interfaces(例如Serializable),也包括fields和methods的所有信息,并可于运行时改变fields内容或调用methods。 一般而言,开发者社群说到动态语言,大致认同的一个定义是:“程序运行时,允许改变程序结构或变量类型,这种语言称为动态语言”。 在JDK中,主要由以下类来实现Java反射机制,这些类都位于 https://www.doczj.com/doc/ee9245245.html,ng.reflect包中: Class类:代表一个类; Field 类:代表类的成员变量(成员变量也称为类的属性); Method类:代表类的方法; Constructor 类:代表类的构造方法; Array类:提供了动态创建数组,以及访问数组的元素的静态方法; 例程DateMethodsTest类演示了Reflection API的基本作用,它读取命令行参数指定的类名,然后打印这个类所具有的方法信息,代码如下: Java代码 1.public class DateMethodsTest 2.{ 3. public static void main(String args[]) throws Exception 4. { 5. // 加载并初始化命令行参数指定的类 6. Class classType = Class.forName("java.util.Date"); 7. // 获得类的所有方法 8. Method methods[] = classType.getDeclaredMethods(); 9. for (int i = 0; i < methods.length; i++) 10. { 11. System.out.println(methods[i].toString());

黑马程序员:java接口回调的经典使用案例

黑马程序员:Java动态代理之通俗理解 代理模式介绍 代理模式是一种常用的设计模式,其作用就是为目标对象提供额外的访问方式,在不修改目标对象的前提下,扩展目标对象的额外功能,比如统计执行时间,打印日志等。代理模式分为两种:静态代理和动态代理。需求:假如不想改动原有代码情况下,并记录用户保存方法的执行时间。示例代码如下: 接口 实现类 静态代理实现 静态代理是在程序运行前产生的,一般来说,代理类和目标类实现同一接口或者有相同的父类

产生代理对象的静态工厂类 客户端

静态代理优缺点: 优点: 1、业务类UserServiceImpl只需要关注业务逻辑本身,保证了业务类的重用性。 2、客户端Client和业务类UserServiceImpl之间没有直接依赖关系,对客户的而言屏蔽了具体实现。 缺点: 1、代理对象的一个接口只服务于一种接口类型的对象,静态代理在程序规模稍大时就无法使用。 2、如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度 动态代理实现 动态代理是程序在运行过程中在JVM内部动态产生的代理对象,代理类可以实现对多种类的代理。动态代理又分为两种:JDK动态代理和CGLIB动态代理。JDK动态代理

JDK动态代理需先声明一个代理类和目标类之间的中间类,此中间类需要实现jdk中的一个接口InvocationHandler。源码如下: 产生代理对象的中间类

客户端

JDK动态代理中,需要关注的两点:1、Proxy.newProxyInstance(classLoader, interfaces, this); 底层是怎么创建的代理对象2、invoke方法是什么时候执行的,谁来调用的此方法 解析1>>怎么产生代理对象:

Java设计模式之代理模式

Java设计模式之代理模式 引言 Java 动态代理机制的出现,使得Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。通过阅读本文,读者将会对Java 动态代理机制有更加深入的理解。本文首先从Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现。 代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。 图1. 代理模式 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。 相关的类和接口 要了解Java 动态代理的机制,首先需要了解以下相关的类或接口: https://www.doczj.com/doc/ee9245245.html,ng.reflect.Proxy:这是Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。

由图可见,Proxy 类是它的父类,这个规则适用于所有由Proxy 创建的动态代理类。而且该类还实现了其所代理的一组接口,这就是为什么它能够被安全地类型转换到其所代理的某接口的根本原因。

JAVA常见面试题及解答2015版

JAVA常见面试题及解答(精华) 1)transient和volatile是java关键字吗?(瞬联) 如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。例如:class T { transient int a; //不需要维持 int b; //需要维持 } 这里,如果T类的一个对象写入一个持久的存储区域,a的内容不被保存,但b 的将被保存。 volatile修饰符告诉编译器被volatile修饰的变量可以被程序的其他部分改变。在多线程程序中,有时两个或更多的线程共享一个相同的实例变量。考虑效率问题,每个线程可以自己保存该共享变量的私有拷贝。实际的变量副本在不同的时候更新,如当进入synchronized方法时。用strictfp修饰类或方法,可以确保浮点运算(以及所有切断)正如早期的Java版本那样准确。切断只影响某些操作的指数。当一个类被strictfp修饰,所有的方法自动被strictfp修饰。 strictfp的意思是FP-strict,也就是说精确浮点的意思。在Java虚拟机进行浮点运算时,如果没有指定strictfp关键字时,Java的编译器以及运行环境在对浮点运

算的表达式是采取一种近似于我行我素的行为来完成这些操作,以致于得到的结果往往无法令你满意。而一旦使用了strictfp来声明一个类、接口或者方法时,那么所声明的范围内Java的编译器以及运行环境会完全依照浮点规范IEEE-754来执行。因此如果你想让你的浮点运算更加精确,而且不会因为不同的硬件平台所执行的结果不一致的话,那就请用关键字strictfp。 你可以将一个类、接口以及方法声明为strictfp,但是不允许对接口中的方法以及构造函数声明strictfp关键字,例如下面的代码: strictfp interface A {} public strictfp class FpDemo1 { strictfp void f() {} } 2. 错误的使用方法 interface A { strictfp void f(); } public class FpDemo2 { strictfp FpDemo2() {} } 一旦使用了关键字strictfp来声明某个类、接口或者方法时,那么在这个关键字所声明的范围内所有浮点运算都是精确的,符合IEEE-754规范

Java 动态代理机制分析及扩展

引言 Java 动态代理机制的出现,使得 Java 开发人员不用手工编写代理类,只要简单地指定一组接口及委托类对象,便能动态地获得代理类。代理类会负责将所有的方法调用分派到委托对象上反射执行,在分派执行的过程中,开发人员还可以按需调整委托类对象及其功能,这是一套非常灵活有弹性的代理框架。通过阅读本文,读者将会对 Java 动态代理机制有更加深入的理解。本文首先从 Java 动态代理的运行机制和特点出发,对其代码进行了分析,推演了动态生成类的内部实现。 代理:设计模式 代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。 图 1. 代理模式 为了保持行为的一致性,代理类和委托类通常会实现相同的接口,所以在访问者看来两者没有丝毫的区别。通过代理类这中间一层,能有效控制对委托类对象的直接访问,也可以很好地隐藏和保护委托类对象,同时也为实施不同控制策略预留了空间,从而在设计上获得了更大的灵活性。Java 动态代理机制以巧妙的方式近乎完美地实践了代理模式的设计理念。 相关的类和接口 要了解 Java 动态代理的机制,首先需要了解以下相关的类或接口: https://www.doczj.com/doc/ee9245245.html,ng.reflect.Proxy:这是 Java 动态代理机制的主类,它提供了一组静态方法来为一组接口动态地生成代理类及其对象。 清单 1. Proxy 的静态方法

?https://www.doczj.com/doc/ee9245245.html,ng.reflect.InvocationHandler:这是调用处理器接口,它自定义了一个 invoke 方法,用于集中处理在动态代理类对象上的方法调用,通常在该方法中实现对委托类的代理访问。 清单 2. InvocationHandler 的核心方法 每次生成动态代理类对象时都需要指定一个实现了该接口的调用处理器对象(参见 Proxy 静态方法 4 的第三个参数)。 ?https://www.doczj.com/doc/ee9245245.html,ng.ClassLoader:这是类装载器类,负责将类的字节码装载到 Java 虚拟机(JVM)中并为其定义类对象,然后该类才能被使用。Proxy 静态方法生成动态代理类同样需要通过类装载器来进行装载才能使用,它与普通类的唯一区别就是其字节码是由 JVM 在运行时动态生成的而非预存在于任何一个 .class 文件中。 每次生成动态代理类对象时都需要指定一个类装载器对象(参见 Proxy 静态方法 4 的第一个参数) 代理机制及其特点 首先让我们来了解一下如何使用 Java 动态代理。具体有如下四步骤: 1.通过实现 InvocationHandler 接口创建自己的调用处理器; 2.通过为 Proxy 类指定 ClassLoader 对象和一组 interface 来创建动态代理类; 3.通过反射机制获得动态代理类的构造函数,其唯一参数类型是调用处理器接口类型; 4.通过构造函数创建动态代理类实例,构造时调用处理器对象作为参数被传入。 清单 3. 动态代理对象创建过程

相关主题
文本预览
相关文档 最新文档