1 获取Class对象三种方式

//1 对象的静态方法
Class clazz1 = Person.class;
//2 最常用的方式
Class<?> clazz2 = Class.forName(“reflect.Person”);
//3 如果有对象了,可以使用这种方式
Person person = new Person();
Class<? extends Person> clazz3 = person.getClass();
//4 通过类加载器加载(不常用)
Class<?> clazz4 = ClassLoader.getSystemClassLoader().loadClass(“reflect.Person”);

由于反射一般使用在运行时并不知道是那种类型,因此(1,3)并不常用,对象都已经存在了,此时就没有必要用到反射了

2 运用

//getMethods 获取所有的公有方法
//getMethod 获取的公有方法

//getDeclaredMethods 获取所有私有的方法
//getDeclaredMethod 获取私有的方法
//setAccessible(true) 解除私有限定

//获取构造器数组 按照类中的定义的顺序
Constructor<?>[] constructors = clazz.getConstructors();

3 动态代理

AOP的拦截功能是由java中的动态代理来实现的。说白了,就是在目标类的基础上增加切面逻辑,生成增强的目标类(该切面逻辑或者在目标类函数执行之前,或者目标类函数执行之后,或者在目标类函数抛出异常时候执行。不同的切入时机对应不同的Interceptor的种类,如BeforeAdviseInterceptor,AfterAdviseInterceptor以及ThrowsAdviseInterceptor等)。

3.1 jdk动态代理

jdk动态代理是jdk原生就支持的一种代理方式,它的实现原理,就是通过让target类和代理类实现同一接口,代理类持有target对象,来达到方法拦截的作用,这样通过接口的方式有两个弊端,一个是必须保证target类有接口,第二个是如果想要对target类的方法进行代理拦截,那么就要保证这些方法都要在接口中声明,实现上略微有点限制。

  1. public interface GoodsService {
  2. public void sale();
  3. public void show();
  4. }
  1. public class GoodsServiceImpl implements GoodsService {
  2. @Override
  3. public void sale() {
  4. System.out.println("我有商品要卖");
  5. }
  6. @Override
  7. public void show() {
  8. System.out.println("展示商品。。");
  9. }
  10. }
  1. public static void fun1(){
  2. GoodsServiceImpl goodsService = new GoodsServiceImpl();
  3. GoodsService proxy = (GoodsService)Proxy.newProxyInstance(GoodsServiceImpl.class.getClassLoader(),
  4. GoodsServiceImpl.class.getInterfaces(),new InvocationHandler(){
  5. @Override
  6. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  7. System.out.println("我是商品的代理商");
  8. Object invoke = method.invoke(goodsService, args);
  9. System.out.println("完了");
  10. return invoke;
  11. }
  12. });
  13. proxy.sale();
  14. }

上面的方式会对所有的方法进行代理

  1. public class MyInvocationHandler implements InvocationHandler {
  2. private Object object;
  3. MyInvocationHandler() {
  4. super();
  5. }
  6. public MyInvocationHandler(Object o){
  7. object = o;
  8. }
  9. @Override
  10. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  11. Object invoke = null;
  12. if (Objects.equals(method.getName(),"sale()")){
  13. System.out.println("代理卖东西。。。");
  14. invoke = method.invoke(object);
  15. }else {
  16. method.invoke(object);
  17. }
  18. return invoke;
  19. }
  20. }
  21. public static void fun2(){
  22. GoodsServiceImpl goodsService = new GoodsServiceImpl();
  23. GoodsService proxyInstance = (GoodsService)Proxy.newProxyInstance(goodsService.getClass().getClassLoader(),
  24. goodsService.getClass().getInterfaces(), new MyInvocationHandler(goodsService));
  25. proxyInstance.show();
  26. }
  27. }

将代理的方法分离出来

3.2 cglib动态代理实现

cglib 代理不需要目标类继承一个接口, 是一个强大的高性能的代码生成包,它可以在运行期扩展java类与实现java接口

  1. public class TargetService {
  2. public void save(){
  3. System.out.println("do someting ...");
  4. }
  5. }
  6. public class ProxyFactory implements MethodInterceptor {
  7. private Object target;
  8. public ProxyFactory(){
  9. super();
  10. }
  11. public ProxyFactory(Object object){
  12. target = object;
  13. }
  14. public Object getProxyInstance(){
  15. Enhancer enhancer = new Enhancer();
  16. enhancer.setSuperclass(target.getClass());
  17. enhancer.setCallback(this);
  18. return enhancer.create();
  19. }
  20. @Override
  21. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  22. System.out.println("开启事务。。。");
  23. Object invoke = method.invoke(target, objects);
  24. System.out.println("提交事务。。。");
  25. return invoke;
  26. }
  27. }
  1. public class CglibTest {
  2. public static void main(String[] args) {
  3. TargetService targetService = new TargetService();
  4. ProxyFactory proxyFactory = new ProxyFactory(targetService);
  5. TargetService proxyInstance = (TargetService)proxyFactory.getProxyInstance();
  6. proxyInstance.save();
  7. }
  8. }

4、需要注意的问题

需要注意的是,当一个方法没有被aop事务包裹,在该方法内部去调用另外一个有aop事务包裹的方法时,这个方法的aop事务不会生效。

  1. public void register() {
  2. aopRegister();
  3. }
  4. @Transactional
  5. public void aopRegister() {
  6. }

因为通过上面的分析我们知道,在spring中,无论通过jdk的形式还是cglib的形式,代理类对target对象的方法进行拦截,其实都是通过让代理类持有target对象的引用,当外部引用aop包围的方法时,调用的其实是代理类对应的方法,代理类持有target对象,便可以控制target方法执行时的全方位拦截。

而如果在target的内部方法register调用一个aop包围的target方法aopRegister,调用的其实就是target自身的方法,因为这时候的this指针是不可能指向代理类的。所以事务是不能生效的。

https://blog.csdn.net/heyutao007/article/details/49738887