1.Java反射机制
静态语言(强类型语言):
静态语言是在编译时变量的数据类型既可确定的语言,在使用变量之前必须声明数据类型。
例如:C、C++、Java
动态语言 (弱类型语言)
动态语言是在运行时才确定数据类型的语言,程序运行时课改变结构和数据类型。
Java反射机制
程序运行时,对于任意一个类,都能知道这个类的所有方法和属性;对于任意一个对象,都能够调用它的方法和属性
Class类
注意:当Java虚拟机载入一个类的时候, 它就会自动创建一个Class类的实例来表示这个类,该实例中包含了完整的类的结构信息,这个对象像一面镜子一样将类的结构展示给我们,所以我们成为"反射"。
Java反射实现:
利用Class实例实现反射机制:因为Class类的构造函数是Private,不能通过new的方式来创建Class实例,只有JVM有权力一般有三种方式:
1.类名.Class
2.getClass()
3.通过全类名获取,用的较多
注意:每一个类只对应一个`在这里插入代码片`
Class cc=Class.forName("cn.gok.beans.User");
System.out.println("获得类名(全名):"+cc.getName());
System.out.println("获得类名(名字):"+cc.getSimpleName());
Object obj=new User(12,"swag","123");
// 获取类的属性
Field[] fields =cc.getFields();
for (Field field : fields){
System.out.println(field.getName());//获取属性名
}
/*
* 类的反射也可以获得方法
* */
//获得指定方法
Method method = cc.getDeclaredMethod("eate",String.class);
method.invoke(obj,"花生米");//执行该方法
System.out.println("end..............");
实体类
@Table("user")
public class User {
@Column("id")
private Integer id;//用户ID
@Column("username")
private String name;//用户名
@Column("password")
private String psw;//用户密码
String phone;//电话号码
/*
* 构造函数
* */
// 无参构造
public User() {
}
// 有参构造
public User(Integer id, String name, String psw) {
this.id = id;
this.name = name;
this.psw = psw;
}
/*
* 吃的方法
* */
public void eate() {
System.out.println("早餐:面包+牛奶");
}
public void eate(String s) {
System.out.println("早餐:面包+牛奶"+" "+s);
}
自定义注解
@Target(ElementType.FIELD)//作用在字段
@Retention(RetentionPolicy.RUNTIME)//运行时注解,可以通过类的反射获取
public @interface Column {
String value();
}
@Target(ElementType.TYPE)//作用在类或接口
@Retention(RetentionPolicy.RUNTIME)//运行时注解,可以通过类的反射获取
public @interface Table {
String value();//当注解只有一个变量时 变量名必须为value
}
测试
public void test2() throws Exception {
User user=new User(1,"dsk","qwer");
//获得类信息
Class cc=user.getClass();
// cc.isAnnotationPresent(Table.class):判断是否有该注解
System.out.println(cc.isAnnotationPresent(Table.class));
// cc.getAnnotation(Table.class) 获得该注解
Table table= (Table) cc.getAnnotation(Table.class);
System.out.println(table.value());
}
2.了解静态代理实现
Java设计模式–代理模式
为其他对象提供一种代理,从而实现对这个对象的访问控制。在某些情况下,一个对象不能直接引用另一个对象,代理对象可以在客户端和目标对象之间起到中介的作用。
(代理模式用来扩展新功能,在不修改源码的情况下,使用代理模式需要一个代理对象)
代理模式的静态代理的实现
1.创建一个接口(JDK的代理都是面向接口的)
2.创建具体实现类来实现这个接口
3.再创建一个代理类实现这个接口,具体实现类的方法中需要将接口中定义的方法的业务逻辑实现,而代理类中的方法只要调用具体类中的方法就行
接口
public interface UserDao {
// 注册用户
public int registUser(User user);
// 删除用户
public int delUser(int id);
}
实现类
public class UserDaoImpl implements UserDao {
@Override
public int registUser(User user) {
System.out.println("调用数据库添加用户");
return 0;
}
@Override
public int delUser(int id) {
System.out.println("调用数据库删除用户:"+id);
return 1;
}
}
代理实现类
public class UserDaoProxy implements UserDao {
private UserDaoImpl userDaoImpl= new UserDaoImpl();
@Override
public int registUser(User user) {
return 0;
}
@Override
public int delUser(int id) {
System.out.println("代理增强");
int out=userDaoImpl.delUser(id);
return out;
}
}
静态代理的缺陷:使用静态代理,可以知道每一个代理类只能为一个接口服务,如果有多个接口则需要多个代理类与之对应,那么在开放过程中会产生许多的代理,不利于代码的维护,所以引出了动态代理。
3.动态代理的方式
动态代理分为两种,JDK的代理和CGLB的动态代理
1.JDk的动态代理依赖具体的接口,需要代理类有对应的接口类型
2.CGLB代理不依赖具体的接口,功能更加强大,被代理类可以是一个没有接口的类,需要实现
MethodInterceptor接口
public class JDKProxy implements InvocationHandler {
private Object obj;
public JDKProxy(Object obj) {
this.obj = obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(proxy.getClass().getName());
System.out.println("传入参数:"+ JSON.toJSONString(args));
System.out.println("JDK 代理之前");
Object o= method.invoke(obj,args);
return o;
}
}
public class TestCGLIB implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("CGLIB执行前!");
Object out=methodProxy.invokeSuper(o,objects);
System.out.println("CGLIB执行之后!");
return out;
}
}