一、 反射
反射是在程序运行状态下,动态获取类的结构(属性,构造器,方法,注解),动态的创建类对象然后调用类中的属性方法。反射的起源Class,Class中包含类反射要使用的API
获取Class的方法
public class Student{private Integer sId;private String sName;private Integer getsId() {return sId;}private void setsId(Integer sId) {this.sId = sId;}private String getsName() {return sName;}private void setsName(String sName) {this.sName = sName;}public Student(Integer sId, String sName) {this.sId = sId;this.sName = sName;}
}
反射的方法:
0) 获取类类型 对象
Class<Student> stu = Student.class
0.5)获取类 对象
Student stuObj = stu.new Instance() //默认获取无参构造方法
等价于
Student stuObj = stu.getConstructor().new Instance()
1)获取属性
Field sName = stu.getDeclaredField(''sName'')
sName.setAccessible(true)
Field sId = stu.getDeclaredField("sId")
sId.setAccessible(true)
属性设置值
sName.set(stuObj,''张三'')
sId.set(stuObj,1)
2)获取方法
Method getsId = stu.getMethod("getsId")
getsId.invoke(stuObj)
3) 获取构造方法
Constructor c = stu.getConstructor(Integer.class,String.class)
Student s = c.new Instance(1,"张三")
注意事项:
反射获取方法,构造方法,属性方法中 方法名都有加Declared 与 不加Declared。
不加Declared:能够获取父子类中所有public修饰的方法
追加Declared:能够获取当前类中所有修饰符的方法
二)类加载
方法区:放置读取的.class文件
堆区:放置class文件生成的class对象
类加载的过程:
1)转载:查找并加载class文件
2)链接:
验证:验证字节码文件是否符合JVM规范。
准备:为类的静态变量分配内存,初始化化默认值
解析:类中的符号引用转换为直接引用
3)初始化:为类的静态变量赋予正确的初始值
三)Proxy 代理模式
Spring 框架:
IOC控制反转:把项目javabean对象的创建以继生命周期交给spring框架管理
需要使用bean对象时,直接从Spring容器(bean对象的容器)中获取。
利用java的反射,实例化bean对象
AOP面向切面编程:两种动态代理实现
jdk动态代理:实现接口
cglib动态代理:单独的类,没有实现接口
在不修改源代码的情况下扩展功能
静态代理:
目标对象:执行类中方法
代理对象:代理对象中包含目标对象,调用执行对象时可以额外添加功能
注意:静态代理是提前写死的.class文件,并且两个对象类实现同一个接口。跟接口耦合性太高,改动麻烦。
动态代理:
jdk动态代理:
实现InvocationHandler接口,重写invoke方法
1)第一种方式: 直接调用invoke方法
我们在其中内置一个Object对象用来实现对目标方法的调用
public class SqlsessionutilProxyJDK implements InvocationHandler {private Object obj; //代表目标对象@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();if ("get".startsWith(name)||"select".startsWith(name)){Object invoke = method.invoke(obj, args);return invoke;}else {try {SqlSession session = SqlSessionUtil.getSession();Object invoke = method.invoke(obj, args);session.commit();return invoke;} catch (Exception e) {SqlSessionUtil.rollbackSession();throw new RuntimeException(e);}}} }
在Test类中
SqlsessionutilProxyJDK sqlsessionutilProxyJDK = new SqlsessionutilProxyJDK(); Object[] objects = {2,"在职"}; EmpService o =(EmpService) Proxy.newProxyInstance(new EmpServiceImpl().getClass().getClassLoader(), new EmpServiceImpl().getClass().getInterfaces(), new EmpServiceProxyJDK()); Method set = new EmpServiceImpl().getClass().getMethod("set", Integer.class, String.class); sqlsessionutilProxyJDK.setObj(new EmpServiceImpl()); sqlsessionutilProxyJDK.invoke(o, set, objects);2)简化方式:调用代理对象的相应方法
public class SqlsessionutilProxyJDK implements InvocationHandler {private Object obj;public void setObj(Object obj) {this.obj = obj;}public Object proxyInstance(Object obj){this.obj = obj;Object o = Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), this);return o;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {String name = method.getName();if ("get".startsWith(name)||"select".startsWith(name)){Object invoke = method.invoke(obj, args);return invoke;}else {try {SqlSession session = SqlSessionUtil.getSession();Object invoke = method.invoke(obj, args);session.commit();return invoke;} catch (Exception e) {SqlSessionUtil.rollbackSession();throw new RuntimeException(e);}}} }
在Test类中:
cglib代理:
针对没有接口的类实现代理,实质上是创建这个类的子类,子类对象是代理对象,这个类对象是目标对象
需要在pom文件中引入第三方jar包 。如果在普通的java项目中,还需要有该jar包对应的依赖,但在Maven中会自动添加该jar包的依赖。
<!-- cglib--><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.2.12</version></dependency>
public class CGLIBProxy implements MethodInterceptor {public Object getProxyInstance(Object obj){Enhancer enhancer= new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);return enhancer.create();}@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("执行拓展功能");Object o1 = methodProxy.invokeSuper(o, objects);return o1;} }
在测试类中