Java中的反射,动态代理,AOP,三者息息相关,所以放在一起。动态代理底层就是用到反射技术,而SpringAop,就是基于java的动态代理,所谓反射,就是根据一个类的实例去挖掘这个类的信息,包括属性,函数,构造函数,注解等。有种逆向思维的感觉,一般我们是根据class去new 一个instance,现在是根据这个instance去反查对应的class。关于反射的例子,网上例子很多,一搜一堆,例如:Java中的反射
重点关注有关注解的反射,从而我们可以自定义注解,实现一些功能,减少代码重复,而且使得代码简洁,例如缓存注解,日子注解,权限注解等等,通过反射,查找带有自定义注解的类或接口,而注入你想实现的功能。有空再补充示例代码。
动态代理就是实现上面的功能,动态代理有两种,JDK的和Cglib的。
Java动态代理只能代理接口的原因在于Java语言的继承机制。Java是一种单继承的语言,即一个类只能继承一个父类,但可以实现多个接口。动态代理机制通过在运行时生成一个代理类,这个代理类会继承java.lang.reflect.Proxy类,并且实现被代理类的接口。
由于Java不支持多重继承,即一个类不能同时继承多个类,因此动态代理只能通过实现接口的方式来为原有类添加新的功能或限制访问。
具体来说,JDK动态代理通过Proxy.newInstance()方法实现,它需要传入一个接口类。这是因为动态代理机制本身的设计决定了它只能通过接口来实现代理功能。动态代理生成的代理类会继承Proxy类并实现被代理的接口,这样可以通过接口调用代理类的方法,实现对原有功能的增强或扩展。
Java动态代理,动态生成的代理类默认已经继承了Proxy类。而java是单继承,所以无法代理一个类,只能根据接口来进行代理!
动态代理后生成的代理类是这个样子的:public final class $Proxy0 extends Proxy implements YourInterface {}
所以,只能代理接口,而无法代理一个具体的类。
Cglib是代理Class的,因此Class里的函数不能用final 修饰。需要引入依赖:
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.3.0</version>
</dependency>
分别给出示例代码:
package com.cloud.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKDynamicProxy {
/**
* 动态代理为什么只能代理有接口?
*
* Java动态代理,动态生成的代理类默认已经继承了Proxy类。而java是单继承,所以无法代理一个类,只能根据接口来进行代理!
* 动态代理后生成的代理类是这个样子的:public final class $Proxy0 extends Proxy implements YourInterface {}
* 所以,只能代理接口,而无法代理一个具体的类。
*
*/
class MyJDKProxy implements InvocationHandler {
private Object targetObject;
public Object getInstance(Object targetObject){
this.targetObject = targetObject;
return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(), targetObject.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("proxy: before action, proxy change the method action ");
Object resutl = method.invoke(targetObject, args);
System.out.println("proxy: after action");
// 还可对结果 resutl 进行处理,甚至完全改变原函数的执行。
return resutl;
}
}
interface BusinessProxyService {
boolean doit1(String id);
String sayHello(String name);
}
class BusinessProxyServiceImpl implements BusinessProxyService {
@Override
public boolean doit1(String id) {
return false;
}
@Override
public String sayHello(String name) {
System.out.println("hello "+name);
return "hello "+name;
}
}
public static void main(String[] args){
JDKDynamicProxy example = new JDKDynamicProxy();
example.show();
}
public void show(){
MyJDKProxy proxy1 = new MyJDKProxy();
// BusinessProxyService 是接口, 实现类是BusinessProxyServiceImpl
BusinessProxyService target = new BusinessProxyServiceImpl();
BusinessProxyService ap = (BusinessProxyService) proxy1.getInstance(target);
ap.sayHello("Tom");
BusinessProxyService BusinessProxyServiceProxy = (BusinessProxyService) Proxy.newProxyInstance(
target.getClass().getClassLoader(),
target.getClass().getInterfaces(),
proxy1
);
BusinessProxyServiceProxy.sayHello("Tony");
}
}
CGLIB动态代理 被代理的类的成员方法不能有final 修饰
package com.cloud.proxy;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
class UserServiceImpl {
public void saveUser(String username) {
System.out.println("Saving user: " + username);
}
}
class LogInterceptor implements MethodInterceptor {
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
System.out.println("Before method: " + method.getName());
Object result = proxy.invokeSuper(obj, args);
System.out.println("After method: " + method.getName());
return result;
}
}
/**
* CGLIB动态代理 被代理的类的成员方法不能有final 修饰
*/
public class CglibProxyExample {
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(new LogInterceptor());
UserServiceImpl proxy = (UserServiceImpl) enhancer.create();
proxy.saveUser("Bob");
}
}
spring 的拦截器,AOP等技术就是基于上面技术实现的。
package com.cloud.aop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Component
public class AspectText
{
private static final Logger l = LoggerFactory.getLogger(AspectText.class);
public String b(String name){
l.info("name:{}",name);
return "你真帅";
}
}
package com.cloud.aop;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.logging.Logger;
@Component
public class JuiLogDemo
{
private static final Logger LOGGER = Logger.getLogger(JuiLogDemo.class.getName());
@Autowired
AspectText aspectText;
public void logs(String name)
{
aspectText.b(name);
}
}
package com.cloud.aop;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Arrays;
@Aspect//定义该类为切面
@Component
public class LogAspect
{
@Pointcut("execution(* com.cloud.aop.JuiLogDemo.*(..))")//切点表达式
public void aspectPointcut() { }
@Around("aspectPointcut()")
public Object interceptor (ProceedingJoinPoint pjp){
String methodName=pjp.getSignature().getName();
String className=pjp.getTarget().getClass().getName();
Object [] args=pjp.getArgs();
//MethodInvocationProceedingJoinPoint p = (MethodInvocationProceedingJoinPoint) pjp;
Method method = ((MethodSignature) pjp.getSignature()).getMethod();
RepeatAnnotation repeatAnnotation=method.getAnnotation(RepeatAnnotation.class);
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
System.out.println("before Method invoke:"+className+"-->"+methodName);
System.out.println("before Method invoke:");
Arrays.stream(args).forEach(obj->{System.out.println(obj);});
System.out.println("before Method invoking");
Object res=null;
try {
res = pjp.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}finally {
}
System.out.println("After Method invoke:"+res);
return res;
}
}