一,反射
概念
Java反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意方法和属性;这种动态获取信息以及动态调用对象方法的功能就是Java语言的反射机制.简单来说,就是反射可以帮助我们在动态运行的时候,对于任意一个类,可以获得其所有方法,所有的变量(是所有的!包括私有!)
作用
1.通过反射可以使程序代码访问装载到JVM 中的类的内部信息
2.获取已装载类的成员变量信息
3.获取已装载类的方法
4.获取已装载类的构造方法信息
常用方法
1.getName()获得类的完整名字
2.getPackage()获取此类所属的包
3.getSuperclass()获得此类的父类对应的Class对象
4.getField(String name)获得类的指定属性
5.getMethods()获得类的public类型的方法
6.getMethod (String name,Class [] args)获得类的指定方法
每个Method对象对应一个方法,获得Method对象后,可以调用其invoke() 来调用对应方法
三种获取类信息的方式
1.对象. getClass( )
通过对象. getClass( ) 方法将会返回一个 Class 类型的实例(多用于对象获取字节码的方式)
2.类名字.class (多用于参数传递)
3.类的路径 (多用于配置文件)
理论上,我们可以通过传来的参数,去创建任意一个类的对象来执行里面的方法和对任意一个类进行读写
创建类A
public class A {
private String a;
}
通过类名反射将A对象的a属性赋值为张三(方法.setAccessible(true);强制访问)
public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException, ClassNotFoundException {
Class<?> bClass = Class.forName("com.study.mybatisdemo.mapper.A");
Field field = bClass.getDeclaredField("a");
field.setAccessible(true);
Object o1=bClass.newInstance();
field.set(o1,"zhangsan");
Object o2=field.get(o1);
System.out.println(o2);
}
代理
概念解释:
代理是一种设计模式,提供了对目标对象另外的访问方式,即通过代理对象访问目标对象。可以不修改目标对象,对目标对象功能进行拓展
代理模式的实现:
代理模式的实现分为两大类:静态实现和动态实现,动态实现根据实现的方式分为:jdk 动态实现,cglib动态实现
1.静态代理
组成部分:
代理目标接口:定义代理类和目标实现类的基本模板,代理类和目标实现类都要实现这个接 口
目标对象: 实现代理目标接口的实现类
代理类: 持有目标对象,根据不同的策略选择不同的方法调用目标对象的方法。
静态代理的优缺点:
优点: 做到不修改目标对象的功能前提下,对目标功能扩展
缺点: 如果有一百万个目标类就得有一百万个静态代理,比较繁琐
实现:
代理目标接口:
public interface Singr {
//唱歌
void singing();
//跳舞
void dance();
}
实现类:
public class Cai implements Singr {
public void singing(){
System.out.println("cai 唱歌");
}
public void dance(){
System.out.println("cai 跳舞");
}
}
静态代理类:
public class StaDai implements Singr {
Cai cai =new Cai();
@Override
public void singing() {
System.out.println("先给钱...");
cai.singing();
System.out.println("谢谢大爷...");
}
@Override
public void dance() {
System.out.println("先给钱...");
cai.dance();
System.out.println("谢谢大爷...");
}
}
执行结果:
先给钱...
cai 唱歌
谢谢大爷...
==============================================
先给钱...
cai 跳舞
谢谢大爷...
2.jdk动态代理
组成部分
1.目标类接口
2.目标实现类
3.Java.lang.reflect.Proxy类的Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
4.InvocationHandler接口的实现类:实现调用目标类的扩展逻辑
JDK动态代理的优缺点:
1. 优点:动态实现了不改变目标对象逻辑的扩展
2.缺点:目标必须实现接口,不然无法实现动态代理
具体实现
代理目标接口:
public interface Singr {
//唱歌
void singing();
//跳舞
void dance();
}
实现类:
public class Cai implements Singr {
public void singing(){
System.out.println("cai 唱歌");
}
public void dance(){
System.out.println("cai 跳舞");
}
}
InvocationHandler接口实现 :
public class Dai implements InvocationHandler {
private Singr singr;
public Dai (Singr singr) {
this.singr=singr;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("给大爷唱歌跳舞");
return method.invoke(singr,args);
}
public static void main(String[] args) {
}
}
main执行:
public class Main2 {
public static void main(String[] args) {
Cai cai =new Cai();
Dai dai = new Dai(cai);
//构建了以被代理类为基准的代理类的一个对象
Object o = Proxy.newProxyInstance(Cai.class.getClassLoader(),Cai.class.getInterfaces(),dai);
Singr singr = (Singr)o;
singr.dance();
singr.singing();
singr.toString();
}
}
执行结果:
给大爷唱歌跳舞
cai 跳舞
给大爷唱歌跳舞
cai 唱歌
给大爷唱歌跳舞
Cglib实现代理
组成部分:
实现类:实现具体目标的逻辑
代理类:实现MethodInterceptor接口,扩展逻辑实现
Enhancer 设置代理类,并且生成代理对象
优缺点:
优点: 实现了不适用接口就可以实现动态代理
缺点:实现类没有统一的限定格式
代理类的思维导图:
我理解的aop
通过springboot里面的xml帮助我们生成代理对象,通过对象来执行方法,同时执行增强方法。
代理目标接口:
public interface TargetInteface {
void method1();
void method2();
int method3(Integer i);
}
实现类:
public class Target implements TargetInteface{
/*
* 需要增强的方法,连接点JoinPoint
**/
public void method1() {
System.out.println("method1 running ...");
}
public void method2() {
System.out.println("method2 running ...");
}
public int method3(Integer i) {
System.out.println("method3 running ...");
return i;
}
}
增强类
public class TargetAdvice implements MethodInterceptor, MethodBeforeAdvice, AfterReturningAdvice {
/*
* 通知/增强
**/
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("前置环绕通知");
Object proceed = methodInvocation.proceed();
System.out.println("后置环绕通知");
return proceed;
}
@Override
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
System.out.println("后置返回通知");
}
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知");
}
}
main方法:
public class AopTest {
public static void main(String[] args) {
ApplicationContext appCtx = new ClassPathXmlApplicationContext("spring-aop.xml");
Target targetProxy = (Target) appCtx.getBean("targetProxy");
targetProxy.method1();
}
}
spring-aop.xml:
<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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="target" class="com.heaboy.aopdemo.aop.Target"/>
<bean id="targetAdvice" class="com.heaboy.aopdemo.aop.TargetAdvice"/>
<bean id="targetProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="target" ref="target"/> <!--被代理的类-->
<property name="interceptorNames" value="targetAdvice"/> <!--如果用多种增强方式,value的值使用逗号(,)分割-->
<property name="proxyTargetClass" value="true"/>
<property name="interfaces" value="com.heaboy.aopdemo.aop.TargetInteface"/> <!--target实现的接口-->
</bean>
</beans>