反射的概述
JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
Java属于先编译再运行的语言,程序中对象的类型在编译期就确定下来了,而当程序在运行时可能需要动态加载某些类,这些类因为之前用不到,所以没有被加载到JVM。通过反射,可以在运行时动态地创建对象并调用其属性,不需要提前在编译期知道运行的对象是谁。
反射的作用
类的加载器可以获得类中的东西:属性,构造方法,功能方法。即
动态创建对象
动态操作属性
动态调用方法
反射的优点
灵活、自由度高:不受类的访问权限限制,想对类做啥就做啥;
反射的缺点
性能问题:通过反射访问、修改类的属性和方法时会远慢于直接操作,但性能问题的严重程度取决于在程序中是如何使用反射的。如果使用得很少,不是很频繁,性能将不会是什么问题;
安全性问题:反射可以随意访问和修改类的所有状态和行为,破坏了类的封装性,如果不熟悉被反射类的实现原理,随意修改可能导致潜在的逻辑问题;
兼容性问题:因为反射会涉及到直接访问类的方法名和实例名,不同版本的API如果有变动,反射时找不到对应的属性和方法时会报异常;
反射的入口——class类

IOC/DI
IOC(控制反转):以前依赖的对象自己直接new,现在不需要new,框架会自动注入,创建对象的权利转移给了框架
DI(依赖注入):一个类的功能需要依赖另一个类的配合,同时需要赋上一个具体的对象,则这种关系是依赖注入
Spring框架负责所有对象的创建、管理和依赖注入,所有对象储存的容器叫做IOC容器
核心配置文件:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
dao层:
package com.zhang.dao;
public interface BookDao {
public void study();
}
package com.zhang.dao.impl;
import com.zhang.dao.BookDao;
public class BookDaoImpl implements BookDao {
@Override
public void study() {
}
}
service层
package com.zhang.service.impl;
import com.zhang.dao.BookDao;
import com.zhang.service.BookService;
public class BookServiceImpl implements BookService {
private BookDao bookDao;
@Override
public void save() {
System.out.println("BookServiceImpl---------save");
bookDao.study();
}
}
package com.zhang.service;
public interface BookService {
void save();
}
servlet层:
package com.zhang.servlet;
import com.zhang.service.BookService;
import com.zhang.service.impl.BookServiceImpl;
import org.junit.Test;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BookServlet {
BookService bookService;
@Test
public void add(){
System.out.println("bookService---------");
ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("Spring.xml");
bookService= (BookService) context.getBean("bookService");
bookService.save();
}
}
动态代理
动态代理是一种常用的设计模式,广泛应用于框架中,Spring框架的AOP特性就是应用动态代理实现的,想要理解AOP的实现原理我们就必须先理解动态代理。
什么是代理模式
代理模式是GOF23设计模式之一,代理模式中存在代理者和被代理者,代理者和被代理者都具有相同的功能,并且代理者执行功能时会附加一些额外的操作
代理模式的优点
符合开闭原则,不用修改被代理者任何的代码,就能扩展新的功能
项目的扩展和维护比较方便
public static void main(String[] args) {
//明确要代理的对象
Actor cxk=new CXK();
/**
* 创建代理对象,具体某个人作为经纪人,对代理对象的方法进行服务(功能增强)
* 参数1,ClassLoader loader 被代理的类的类加载器(底层使用的反射)
* 2,Class<?>[] interfaces 被代理的类的接口类型(类型的判断)
* 3,InvocationHandler h 被代理后要做什么事情
*/
Actor jjr= (Actor) Proxy.newProxyInstance(CXK.class.getClassLoader(), CXK.class.getInterfaces(), new InvocationHandler() {
/**
* Object proxy:被代理对象的一个引用
* Method method:被代理对象的方法
* Object[] args:方法被执行时需要的参数列表
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前置增强
System.out.println("进行巡演造势");
//方法的三要素
Object result=null;
String methodName= method.getName();
System.out.println(methodName);
//方法执行需要一个对象的引用
result=method.invoke(cxk,args);
//后置增强
System.out.println("结算和纳税");
return result;
}
});
//3,执行方法,由代理对象进行执行
jjr.sing(5,3.14);
jjr.rap();
}
}
AOP
AOP全名Aspect-oriented programming面向切面编程大法,它有很多兄弟,分别是经常见的面向对象编程,朴素的面向过程编程和神秘的函数式编程等。AOP实现的关键在于AOP框架自动创建的AOP代理,AOP代理主要分为静态代理和动态代理
AOP是什么原理?
AOP代表的是一个横向的关系,相比于纵向的继承关系更加简便。将“对象”比作一个空心的圆柱体,其中封装的是对象的属性和行为;则面向方面编程的方法,就是将这个圆柱体以切面形式剖开,可以选择性的提供业务逻辑。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹,但完成了效果。
Spring AOP 底层实现
JDK 动态代理:基于接口实现
CGLib 是基于类的继承实现的
首先导入IOC和AOP所需要的jar包

创建UserService类,这个类完成核心功能操作。
void findAll();
void save(int a);
int del();
void update();
/**
* 核心类
*/
public class BookServiceImpl implements BookService {
@Override
public void findAll() {
System.out.println("查询所有");
}
@Override
public void save(int a) {
System.out.println("保存信息"+a);
}
@Override
public int del() {
System.out.println("删除信息");
return 5;
}
@Override
public void update() {
System.out.println("修改信息");
}
}
创建Logger类,这个类是用来做功能的增强。
/**
* 增强类
*/
public void check() {
System.out.println("前置通知/增强:权限验证");
}
public void logprint(){
System.out.println("后置通知/增强:日志输出");
}
public void exception(){
System.out.println("异常通知/增强:异常处理");
}
public void distory(){
System.out.println("最终通知/增强:资源释放");
}
}
在spring的beans.xml中开始进行AOP的配置:
首先把核心类和增强类的bean配置到IOC的容器中使用<aop:config>标签在进行AOP的配置,先通过aop:aspect标签标明谁是增强类。然后在标签中进行aop:before(前置)、aop:after-returning(后置)、aop:after-throwing(异常)、aop:after(最终)的配置,让增强类的某个方法对核心功能类的某一类方法进行功能增强。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--1.把所有类的对象交给IOC容器进行管理-->
<bean id="logger" class="com.gao.logger.Logger"/>
<bean id="bookService" class="com.gao.service.impl.BookServiceImpl"/>
<!--2.AOP的配置:让增强类 的 哪个方法 动态进行何种增强 核心类 的 哪个方法-->
<aop:config>
<!--指定增强类并起个名字-->
<aop:aspect id="check" ref="logger">
<!--前置通知/增强:在核心类方法执行之前 进行 增强-->
<aop:before method="check" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:before method="logprint" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:before method="exception" pointcut="execution(* *..BookServiceImpl.*(..))"/>
<aop:before method="distory" pointcut="execution(* *..BookServiceImpl.*(..))"/>
</aop:aspect>
</aop:config>
</beans>
本文介绍了Java反射机制的概念、作用及优缺点,重点讲解了反射的入口Class类。接着讨论了IOC/DI,解释了控制反转和依赖注入的概念,并阐述了Spring框架中的应用。此外,文章还深入探讨了动态代理,包括其优点和在Spring AOP中的应用。最后,简单介绍了AOP的原理和Spring AOP的底层实现,包括JDK动态代理和CGLib。

302

被折叠的 条评论
为什么被折叠?



