一般情况:
租房接口:
//租房
public interface Rent {
public void rent();
}
房东类:
//房东
public class Host implements Rent {
@Override
public void rent() {
System.out.println("房东出租房子");
}
}
顾客类:
public class Client {
public static void main(String[] args) {
Host host = new Host();
host.rent();
}
}
出现了代理角色:
public class Proxy implements Rent{
private Host host;//组合
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
host.rent();
}
}
则顾客可以通过代理租房:
public class Client {
public static void main(String[] args) {
Host host = new Host();
//代理
Proxy proxy = new Proxy(host);
proxy.rent();
}
}
代理角色可以有一些自己的附属操作,属于自己的功能,,否则代理没有意义:
public class Proxy implements Rent{
private Host host;//组合
public Proxy() {
}
public Proxy(Host host) {
this.host = host;
}
public void rent(){
seeHouse();
hetong();
fare();
host.rent();
}
//代理的附属操作
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
//签合同
public void hetong(){
System.out.println("签合同");
}
}
代理模式的好处:
可以使真实角色的操作更加纯粹,不用关注一些公共的业务。 公共业务就交给代理角色。实现了业务的分工。 公共业务发生扩展的时候,方面集中管理。缺点:
一个真实角色就会产生一个代理对象,代码量会翻倍,开发效率低。 静态代理再理解:根据实际业务模拟:
UserService:
public interface UserService {
public void add();
public void delete();
public void update();
public void query();
}
UserServiceImpl:
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("增加用户");
}
@Override
public void delete() {
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("更新用户");
}
@Override
public void query() {
System.out.println("查询用户");
}
}
此时若需要增加日志功能,则需要在每个实现类的实现方法中,增加日志输出。若有n个实现类,则需要改n*n此,特别麻烦。
例如:
public class UserServiceImpl implements UserService {
@Override
public void add() {
System.out.println("调用了add方法");
System.out.println("增加用户");
}
@Override
public void delete() {
System.out.println("调用了delete方法");
System.out.println("删除用户");
}
@Override
public void update() {
System.out.println("调用了update方法");
System.out.println("更新用户");
}
@Override
public void query() {
System.out.println("调用了query方法");
System.out.println("查询用户");
}
}
违背开闭原则!!!
故引入代理:
public class UserServiceProxy implements UserService{
private UserServiceImpl userServiceImpl;
public UserServiceProxy(UserServiceImpl userServiceImpl) {
this.userServiceImpl = userServiceImpl;
}
@Override
public void add() {
printLog();
userServiceImpl.add();
}
@Override
public void delete() {
printLog();
userServiceImpl.delete();
}
@Override
public void update() {
printLog();
userServiceImpl.update();
}
@Override
public void query() {
printLog();
userServiceImpl.query();
}
public void printLog(){
System.out.println("打印日志");
}
}
改变原来代码是大忌!!!
AOP的理解:
动态代理: 动态代理和静态代理一样 动态代理的代理类是动态生成的,不是我们直接写好的。 动态代理分为两大类:基于接口的动态代理,基于类的动态代理 基于接口—jdk动态代理 基于类—cglib java字节码实现:javasist 基于接口的动态代理:需要了解两个类:Proxy:代理,InvocationHandler
InvocationHandler java.lang.reflect包下 是由代理实例的,调用处理程序实现的接口。每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时,方法调用将被编码并分派到其调用处理程序的invoke方法。 invoke方法是通过反射的方式执行方法。创建动态的代理类:
//自动生成代理类的类
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的接口
private Rent rent;
public void setRent(Rent rent){
this.rent=rent;
}
//生成得到代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
//代理实例:被代理的人
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(rent, args);
return result;
}
}
此时顾客:
public class Client {
public static void main(String[] args) {
//真实角色
Host host = new Host();
//代理
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
proxyInvocationHandler.setRent(host);
Rent proxy = (Rent) proxyInvocationHandler.getProxy();
proxy.rent();
}
}
若需要代理类需要扩展功能:
//自动生成代理类的类
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的接口
private Rent rent;
public void setRent(Rent rent){
this.rent=rent;
}
//生成得到代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),rent.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
//代理实例:被代理的人
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
seeHouse();
fare();
hetong();
Object result = method.invoke(rent, args);
return result;
}
//看房
public void seeHouse(){
System.out.println("中介带你看房");
}
//收中介费
public void fare(){
System.out.println("收中介费");
}
//签合同
public void hetong(){
System.out.println("签合同");
}
}
形成通用的动态代理模板:
//自动生成代理类的类
public class ProxyInvocationHandler implements InvocationHandler{
//被代理的接口
private Object object;
public void setObject(Object object){
this.object=object;
}
//生成得到代理对象
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
//处理代理实例并返回结果
//代理实例:被代理的人
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result = method.invoke(object, args);
return result;
}
}
动态代理的好处:
可以使真实角色的操作更加纯粹,不用关注一些公共的业务。 公共业务就交给代理角色。实现了业务的分工。 公共业务发生扩展的时候,方面集中管理。 一个动态代理类代表的是一个接口,一般就是对应的一类业务。 一个动态代理类可以代理多个类,只要是实现了同一个接口即可。