(1)是什么
AOP意思是面向切面的编程。
(2)有什么用
提供一种方式可以在现有代码前后增加一些统一的逻辑。比如监控、打印日志等。
(3)实现原理
使用动态代理技术实现。有两种实现方式,一个是JDK Proxy,另一个是CgLib。
JDK Proxy要求被代理的对象实现一个接口,通过动态代理动态生成该接口的一个实现类。在实际使用时,需要定义一个中间类实现InvocationHandler接口定义代理类要执行的操作。
CgLib不要求被代理类实现接口,它是一个第三方类库,通过生成一个被代理对象的子类来进行动态代理。
两者在使用上都需要定义一个中间类来指定代理时要执行的额外动作。cglib的优势在于不要求被代理类实现接口,但是是第三方类库,需要额外引入依赖。而JDK Proxy是JDK原生支持的。
JDK Proxy的使用demo如下:
//接口1
public interface IUserService {
String sayHello(String name);
String sayHappy(String name);
}
//接口2
public interface IUser2Service {
String sayBye(String name);
}
/**
* 被代理类
* 要求需要实现一些接口。最终被代理的方法必须是这些接口中的方法
* */
public class UserServiceImpl implements IUserService, IUser2Service {
private static final Logger LOG = LoggerFactory.getLogger(UserServiceImpl.class);
@Override
public String sayHello(String name) {
String res = "hello," + name;
LOG.info(res);
return res;
}
@Override
public String sayHappy(String name) {
String res = "I'm happy to see you,dear " + name;
LOG.info(res);
return res;
}
@Override
public String sayBye(String name) {
String res = "bye," + name;
LOG.info(res);
return res;
}
}
**
* 代理类和被代理类之间的中间类
* 在invoke中定义代理类要执行的动作
* 一般初始化时将被代理类传递进来,方便使用method.invoke执行原方法。
* 最终代理类的对应方法执行时,会调用这里的invoke方法。
* 具体的代理类生成见ProxyTest类
* */
public class LogBeforeAndAfterProxy implements InvocationHandler {
private static final Logger LOG = LoggerFactory.getLogger(LogBeforeAndAfterProxy.class);
private Object target;
public LogBeforeAndAfterProxy(Object target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(proxy, method, args);
Object invoke = method.invoke(target, args);
after(proxy, method, args);
return invoke;
}
private void before(Object proxy, Method method, Object[] args) {
LOG.info("log before " + method.getName());
}
private void after(Object proxy, Method method, Object[] args) {
LOG.info("log after " + method.getName());
}
}
public class ProxyTest {
private static final Logger LOG = LoggerFactory.getLogger(ProxyTest.class);
@Test
public void test() {
IUserService userService = new UserServiceImpl();
LogBeforeAndAfterProxy proxy = new LogBeforeAndAfterProxy(userService);
//代理类的生成,传入被代理类的类加载器、接口列表、中间对象
//这里返回值只能是接口之一,不能是被代理对象的类型
IUserService userServiceProxy = (IUserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), proxy);
//接口的所有方法都可以被代理执行
String tom = userServiceProxy.sayHello("Tom");
String tom2 = userServiceProxy.sayHappy("Tom");
LOG.info(tom);
LOG.info(tom2);
//实现了多个接口,可以分别进行代理
IUser2Service userServiceProxy2 = (IUser2Service) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), proxy);
String tom1 = userServiceProxy2.sayBye("John");
LOG.info(tom1);
}
}
Cglib使用demo如下:
public class UserService {
private static final Logger LOG = LoggerFactory.getLogger(UserService.class);
public String saySomething(String name, String something) {
String res = name + " : " + something;
LOG.info(res);
return res;
}
}
public class CglibProxy implements MethodInterceptor {
private static final Logger LOG = LoggerFactory.getLogger(CglibProxy.class);
private Object target;
public CglibProxy(Object target) {
this.target = target;
}
public Object getProxy() {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
//before
before(o, method, objects, methodProxy);
Object invoke = methodProxy.invoke(target, objects);
//after
after(o, method, objects, methodProxy);
return invoke;
}
private void before(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
LOG.info("log before " + method.getName());
}
private void after(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
LOG.info("log after " + method.getName());
}
}
public class CglibProxyTest {
private static final Logger LOG = LoggerFactory.getLogger(CglibProxyTest.class);
@Test
public void test() {
UserService userService = new UserService();
CglibProxy cglibProxy = new CglibProxy(userService);
UserService proxy = (UserService) cglibProxy.getProxy();
String s = proxy.saySomething("tom", "hello");
LOG.info(s);
}
}