1、java反射机制
java在new出一个对象之后,实际上是将.java文件编译成.class文件,然后jvm加载.class文件并生成.class对象。
而反射则与之相反,通过.class对象反编译获取到.java文件中的属性。
反射的定义:在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。
反射的使用:
// 获取反射class对象的三种方式
public static void main(String[] args) throws ClassNotFoundException {
StringUtils stringUtils = new StringUtils();
// 1、new出对象之后,调用getClass()方法
Class<StringUtils> aClass1 = (Class<StringUtils>) stringUtils.getClass();
// 2、类名.class
Class<StringUtils> aClass2 = StringUtils.class;
// 3、Class.forName()方法
Class<?> aClass3 = Class.forName("com.example.dashboard.util.StringUtils");
System.out.println(aClass1.getName());
System.out.println(aClass1==aClass2);
System.out.println(aClass1==aClass3);
/**
* 打印结果:
* com.example.dashboard.util.StringUtils
* true
* true
*/
}
2、代理
代理:简单的说就是用代理类去执行普通类的方法,简单示例如下:通过Proxy类执行A类中的print方法。
public class Test {
public static void main(String[] args) {
A a = new A();
Proxy proxy = new Proxy(a);
proxy.print();
}
}
class A {
public void print() {
System.out.println("A类");
}
}
class Proxy {
private A a;
public Proxy() {
}
public Proxy(A a) {
this.a = a;
}
public void print() {
a.print();
}
}
3、spring 动态代理
在JVM运行的过程中创建对象。
4、spring启动流程
package com.example.demo.beanDefinition;
import org.springframework.stereotype.Component;
import java.beans.Introspector;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.concurrent.ConcurrentHashMap;
public class DingApplicationContext {
private Class configClass;
private ConcurrentHashMap<String,BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>();
private ConcurrentHashMap<String,Object> singletonObjects = new ConcurrentHashMap<>();
public DingApplicationContext(Class configClass) {
this.configClass = configClass;
if(configClass.isAnnotationPresent(MyComponentScan.class)){
MyComponentScan annotation = (MyComponentScan) configClass.getAnnotation(MyComponentScan.class);
String path = annotation.value(); // 获取到包名
path = path.replace(".", "/");
ClassLoader classLoader = DingApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path); // 拼接出来绝对路径
File file = new File(resource.getFile());
System.out.println(file);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (File f : files) { // 文件夹,过滤出来需要加载的bean
String fileName = f.getAbsolutePath();
System.out.println(fileName);
if (fileName.endsWith(".class")) { // 需要加载的必然是.class文件
String className = fileName.substring(fileName.indexOf("com"), fileName.indexOf(".class"));
className = className.replace("\\",".");
try {
Class<?> clazz = classLoader.loadClass(className);
if(clazz.isAnnotationPresent(Component.class)){
String beanName = clazz.getAnnotation(Component.class).value();
//这个使用以下spring的默认名字取用方法
if("".equals(beanName)){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
// 需要加载的bean
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
beanDefinition.setScope("singleton"); // 需要通过注解@scope进行判断
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
// 获取单例bean
for (String beanName : beanDefinitionMap.keySet()) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition.getScope().endsWith("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
}
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if (beanDefinition == null) {
throw new NullPointerException();
} else {
String scope = beanDefinition.getScope();
if (scope.equals("singleton")) {
Object bean = singletonObjects.get(beanName);
if (bean == null) {
Object o = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, o);
return o;
}
return bean;
} else {
return createBean(beanName, beanDefinition);
}
}
}
}
@MyComponentScan(value = "com.example.demo.beanDefinition")
public class AppConfig {
}
@Data
public class BeanDefinition {
private Class type;
private String scope;
}
@Component("mainService")
public class MainService {
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface MyComponentScan {
String value() default "";
}
public class Test {
public static void main(String[] args) {
DingApplicationContext applicationContext = new DingApplicationContext(AppConfig.class);
MainService mainService = (MainService) applicationContext.getBean("mainService");
}
}
5、bean的初始化
bean初始化的步骤:
1、生成beanDefinition对象
2、将需要生成的bean信息注入beanDefinition
3、User.class -> 推测构造方法-> 普通对象 -> 依赖注入 -> 初始化前@PostConstruct -> 初始化 实现InitializingBean接口实现afterPropertiesSet() -> 初始化后 AOP -> 代理对象 -> 单例放入单例池Map -> Bean对象
构造:如果多个,存在无参,使用无参;没有无参,可以用@Autowired指定;若都没有报错
代理对象 继承 User, 内部存在属性tagert指向普通对象
AOP之后会产生代理对象
spring事务分析:
// spring事务的代码分析, 只有代理对象能触发
class UserProxy extends User {
User target;
public void test() {
// 1、判断是否需要处理事务 @Transactional
// 2、建立一个新的数据库链接conn ThreadLocal<Map<DataSource,conn>>
// 事务管理器中的数据链接conn1 // 如果conn1!=conn2 事务也会失效
// 3、conn.autocommit = false
target.test(); // 执行数据库操作, sql1 sql2 // jdbc中的数据链接conn2
// 方法无异常 conn.commit(); // 异常 conn.rollback()
}
}