代理:
代理模式最主要的就是在不改变原来代码(就是目标对象)的情况下实现功能的增强
在学习AOP之前先了解代理,代理有两种:一种是动态代理,一类是静态代理。
静态代理
相当于是自己写了一个代理类,在调用的时候调用的是代理类,代理类中的处理还是原生的处理逻辑,不过在前后添加上需要增强功能的代码。(类似继承实现的)
缺点:需要为每一个被代理的对象都创建一个代理类。
静态代理实现:
1.创建接口
public interface Target {
public abstract String getExe();
}
2.实现目标对象
public class MyTarget implements Target {
@Override
public String getExe() {
System.out.println("执行ing.....");
return "ok";
}
}
3.实现代理对象
package 反射;
public class Proxy implements Target{
MyTarget myTarget;
public Proxy(MyTarget myTarget) {
this.myTarget = myTarget;
}
@Override
public String getExe() {
System.out.println("权限检查");
String res= myTarget.getExe();
System.out.println("日志打印");
return res;
}
}
4.测试代码
package 反射;
public class demo1 {
public static void main(String[] args) {
MyTarget myTarget=new MyTarget();
Proxy proxy = new Proxy(myTarget);
proxy.getExe();
}
}
动态代理
动态代理模式最大的优势就是不用自己去写一个代理对象,它的代理对象会在java文件编译的时候,通过Java反射去创建的。所以减少了程序员的工作。动态代理的实现有两种方式,现在来介绍一下(基于接口实现)
jdk代理
1.创建接口
package com.aqiuo.jdk;
public interface UserDao {
public void addUser();
public void deleteUser();
}
2.创建实现类
package 代理;
public class UserServiceImpl implements UserService{
public void addUser(){
System.out.println("添加用户");
}
public void delUser(){
System.out.println("删除用户");
}
}
3.编写切面类
package 代理;
public class Aspect {
public void admission(){
System.out.println("权限检查");
}
public void log(){
System.out.println("日志打印");
}
}
4.编写代理类
package 代理;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkProxy implements InvocationHandler {
//用Object型才能动态代理
Object object;
public Object createInstance(Object object){
this.object=object;
Class[] clazz = object.getClass().getInterfaces();
ClassLoader classLoader=JdkProxy.class.getClassLoader();
return Proxy.newProxyInstance(classLoader,clazz,this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Aspect aspect=new Aspect();
aspect.admission();
Object res= method.invoke(object,args);
aspect.log();
return res;
}
}
5.测试:
public class Test {
public static void main(String[] args) {
JdkProxy jdkProxy =new JdkProxy();
UserService userService=new UserServiceImpl();
UserService proxy= (UserService) jdkProxy.createInstance(userService);
proxy.addUser();;
proxy.delUser();
}
}
/**JDK代理有一定局限性,使用动态代理的对象必须实现一个或多个接口,如果要对没有实现接口的类进行代理,可以用CGLIB代理
CGLIB代理
CGLIB是一个高性能的开源代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类增强,已经在Spring中集成
导包
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
MethodInterceptor拦截器
cglib的实现最重要的就是去实现这个MethodInterceptor接口来完成,就像jdk时候的InvocationHandler一样
package com.aqiuo.cglib;
//被代理的类
public class UserDao {
public void addUser() {
// TODO Auto-generated method stub
System.out.println("添加用户");
}
public void deleteUser() {
// TODO Auto-generated method stub
System.out.println("删除用户");
}
}
实现代理类
//代理类
package com.aqiuo.cglib;
import java.lang.reflect.Method;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import com.aqiuo.Aspect.MyAspect;
public class CglibProxy implements MethodInterceptor {
//代理方法
public Object createProxy(Object target) {
//创建一个动态类对象
Enhancer enhancer=new Enhancer();
//确定要增强的类,设置为她的父类
enhancer.setSuperclass(target.getClass());
//添加回调函数
enhancer.setCallback(this);
//返回创建的代理类
return enhancer.create();
}
/**
* ProxyCGlib根据指定的父类,生成代理对象
* method拦截的方法
* args拦截方法的参数数组
* methodProxy方法的代理对象,用来执行父类方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//创建切面类对象
MyAspect myAspect=new MyAspect();
//前增强
myAspect.check_permissions();
//目标方法执行
Object object=methodProxy.invokeSuper( proxy, args);
//后增强
myAspect.log();
return object;
}
}
cglib的原理就是在运行的时候,cglib会自动去生成一个子类,在子类里面去完成增强操作(就是拦截器里面),这里我们来验证cglib就用保存它的子类来查验,也就是将它自动生成的类放在一个指定路径下去看。
//测试类
package com.aqiuo.cglib;
public class CglibTest {
public static void main(String[] args) {
UserDao userDao=new UserDao();
CglibProxy proxy=new CglibProxy();
UserDao userDao2=(UserDao) proxy.createProxy(userDao);
userDao2.addUser();
userDao2.deleteUser();
}
}
cglib动态代理原理:
①创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器②在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))
③创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))
④创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用