控制反转(Ioc)
IoC容器在Spring的实现
Spring 的 IoC 容器就是 IoC思想的一个落地的产品实现。IoC容器中管理的组件也叫做 bean。在创建 bean 之前,首先需要创建IoC 容器。Spring 提供了IoC 容器的两种实现方式:
**①BeanFactory**
这是 IoC 容器的基本实现,是 Spring 内部使用的接口。面向 Spring 本身,不提供给开发人员使用。
**②ApplicationContext**
BeanFactory 的子接口,提供了更多高级特性。面向 Spring 的使用者,几乎所有场合都使用 ApplicationContext 而不是底层的 BeanFactory。
**③ApplicationContext的主要实现类**
package com.zzq.spring6.iocxml; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUser { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean.xml"); //根据id获取bean User user1=(User) context.getBean("user1"); System.out.println(""+user1); //根据类型获取bean User user2=context.getBean(User.class); System.out.println(""+user2); //根据id和类型获取bean User user3=context.getBean("user",User.class); System.out.println(""+user3); } }
如果组件类实现了接口,根据接口类型可以获取 bean 吗?
> 可以,前提是bean唯一
如果一个接口有多个实现类,这些实现类都配置了 bean,根据接口类型可以获取 bean 吗?
> 不行,因为bean不唯一
依赖注入:
1、类有属性,创建对象过程中,向属性设置值
package com.zzq.spring6.iocxml.di; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestBook { @Test public void testSetter(){ ApplicationContext context=new ClassPathXmlApplicationContext("bean-di.xml"); Book book = context.getBean("book", Book.class); System.out.println(book); } }
book.java
package com.zzq.spring6.iocxml.di; public class Book { private String bname; private String author; @Override public String toString() { return "Book{" + "bname='" + bname + '\'' + ", author='" + author + '\'' + '}'; } public String getBname() { return bname; } public void setBname(String bname) { this.bname = bname; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public Book(String bname, String author) { this.bname = bname; this.author = author; } public Book() { } }
bean-di.xml
package com.zzq.spring6.iocxml.di; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestBook { @Test public void testConstructor(){ ApplicationContext context=new ClassPathXmlApplicationContext("bean-di.xml"); Book book = context.getBean("bookCon", Book.class); System.out.println(book); } }
特殊值处理
##### ①字面量赋值
> 什么是字面量?
>
> int a = 10;
>
> 声明一个变量a,初始化为10,此时a就不代表字母a了,而是作为一个变量的名字。当我们引用a的时候,我们实际上拿到的值是10。
>
> 而如果a是带引号的:'a',那么它现在不是一个变量,它就是代表a这个字母本身,这就是字面量。所以字面量没有引申含义,就是我们看到的这个数据本身。
```xml
```
##### ②null值
```xml
```
> 注意:
>
> ```xml
>
> ```
>
> 以上写法,为name所赋的值是字符串null
##### ③xml实体
```xml
```
##### ④CDATA节
```xml
```
第一种方式:
1、创建两个类对象:dept和emp
2、在emp的bean标签里面,使用property引入dept的bean
package com.zzq.spring6.iocxml.ditest; //部门类 public class Dept { private String dname; public void setDname(String dname) { this.dname = dname; } public void info(){ System.out.println("部门名称:"+dname); } }
package com.zzq.spring6.iocxml.ditest; //员工类 public class Emp { //对象类型属性:员工属于某个部门 private Dept dept; private String ename; private Integer age; public Dept getDept() { return dept; } public void work(){ System.out.println(ename+"emp work...."+age); dept.info(); } public void setDept(Dept dept) { this.dept = dept; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
package com.zzq.spring6.iocxml.ditest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestEmp { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean-ditest.xml"); Emp emp = context.getBean("emp", Emp.class); emp.work(); } }
第二种方式:
第三种方式:
package com.zzq.spring6.iocxml.ditest; import java.lang.reflect.Array; import java.util.Arrays; //员工类 public class Emp { //对象类型属性:员工属于某个部门 private Dept dept; private String ename; private Integer age; private String[] loves; public void work() { System.out.println(ename + "emp work...." + age); dept.info(); System.out.println(Arrays.toString(loves)); } public void setLoves(String[] loves) { this.loves = loves; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public String getEname() { return ename; } public void setEname(String ename) { this.ename = ename; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } }
睡觉 听歌 追剧
package com.zzq.spring6.iocxml.ditest; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestDept { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean-dilist.xml"); Dept dept = context.getBean("dept", Dept.class); dept.info(); } }
package com.zzq.spring6.iocxml.ditest; import java.util.List; //部门类 public class Dept { //一个部门有很多员工 private List empList; public List getEmpList() { return empList; } public void setEmpList(List empList) { this.empList = empList; } public String getDname() { return dname; } private String dname; public void setDname(String dname) { this.dname = dname; } public void info(){ System.out.println("部门名称:"+dname); for (Emp emp:empList) { System.out.println(emp.getEname()); } } }
Student类
package com.zzq.spring6.iocxml.dimap; import java.util.Map; public class Student { private String sid; private String name; private Map teacherMap; public void run() { System.out.println("学生编号: " + sid + "学生名称: " + name); System.out.println(teacherMap); } @Override public String toString() { return "Student{" + "sid='" + sid + '\'' + ", name='" + name + '\'' + ", teacherMap=" + teacherMap + '}'; } public Map getTeacherMap() { return teacherMap; } public void setTeacherMap(Map teacherMap) { this.teacherMap = teacherMap; } public String getSid() { return sid; } public void setSid(String sid) { this.sid = sid; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
Teacher类
package com.zzq.spring6.iocxml.dimap; public class Teacher { private String teacherId; private String teacherName; @Override public String toString() { return "Teacher{" + "teacherId='" + teacherId + '\'' + ", teacherName='" + teacherName + '\'' + '}'; } public String getTeacherId() { return teacherId; } public void setTeacherId(String teacherId) { this.teacherId = teacherId; } public String getTeacherName() { return teacherName; } public void setTeacherName(String teacherName) { this.teacherName = teacherName; } }
package com.zzq.spring6.iocxml.dimap; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestStu { @Test public void testStu(){ ApplicationContext context=new ClassPathXmlApplicationContext("bean-dimap.xml"); Student student = context.getBean("student", Student.class); student.run(); } }
1、创建三个对象
2、注入普通类型属性
3、使用util:类型 定义
4、在学生bean引入util:类型定义bean,完成list、map类型属性注入
lesson
package com.zzq.spring6.iocxml.dimap; public class Lesson { private String lessonName; @Override public String toString() { return "Lesson{" + "lessonName='" + lessonName + '\'' + '}'; } public String getLessonName() { return lessonName; } public void setLessonName(String lessonName) { this.lessonName = lessonName; } }
10001 1208
引入p命名空间
10001 1208
package com.zzq.spring6.iocxml.dimap; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestStu { @Test public void testStu(){ ApplicationContext context=new ClassPathXmlApplicationContext("bean-diref.xml"); Student student = context.getBean("studentp", Student.class); student.run(); } }
引入依赖
mysql mysql-connector-java 8.0.30 com.alibaba druid 1.2.15
创建外部属性文件
jdbc.user=root jdbc.password=root jdbc.url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC jdbc.driver=com.mysql.cj.jdbc.Driver
配置bean
测试
package com.zzq.spring6.iocxml.jdbc; import com.alibaba.druid.pool.DruidDataSource; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestJdbc { @Test public void demo1() { DruidDataSource dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mysql://localhost:3306/spring?serverTimezone=UTC"); dataSource.setUsername("root"); dataSource.setPassword("root"); dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver"); } @Test public void demo2(){ ApplicationContext context=new ClassPathXmlApplicationContext("bean-jdbc.xml"); DruidDataSource dataSource = context.getBean(DruidDataSource.class); System.out.println(dataSource.getUrl()); } }
bean的生命周期
package com.zzq.spring6.iocxml.life; public class User { private String name; //无参构造 public User() { System.out.println("1 bean对象创建,调用无参构造"); } //初始化方法 public void initMethod(){ System.out.println("4、bean对象初始化,调用指定的初始化方法"); } //销毁的方法 public void destroyMethod(){ System.out.println("7、bean对象销毁,调用指定的销毁方法"); } public String getName() { return name; } public void setName(String name) { System.out.println("2 给bean对象设置属性值"); this.name = name; } }
package com.zzq.spring6.iocxml.life; import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import org.springframework.lang.Nullable; public class MyBeanPost implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("3、bean后置处理器,初始化之前执行"); System.out.println(beanName+"::"+bean); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("5、bean后置处理器,初始化之后执行"); System.out.println(beanName+"::"+bean); return bean; } }
package com.zzq.spring6.iocxml.life; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUser { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("bean-life.xml"); User user = context.getBean("user", User.class); System.out.println("6 bean对象创建完成,可以使用"); System.out.println(user); context.close();//销毁对象 } }
FactoryBean是Spring提供的一种整合第三方框架的常用机制。和普通的bean不同,配置一个FactoryBean类型的bean,在获取bean的时候得到的并不是class属性中配置的这个类的对象,而是getObject()方法的返回值。通过这种机制,Spring可以帮我们把复杂组件创建的详细过程和繁琐细节都屏蔽起来,只把最简洁的使用界面展示给我们。
将来我们整合Mybatis时,Spring就是通过FactoryBean机制来帮我们创建SqlSessionFactory对象的。
package com.zzq.spring6.iocxml.factorybean; import org.springframework.beans.factory.FactoryBean; public class MyFactoryBean implements FactoryBean { @Override public User getObject() throws Exception { return new User(); } @Override public Class> getObjectType() { return User.class; } }
package com.zzq.spring6.iocxml.factorybean; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUser { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean-factorybean.xml"); User user =(User) context.getBean("user"); System.out.println(user); } }
package com.zzq.spring6.iocxml.factorybean; public class User { }
package com.zzq.spring6.iocxml.auto.controller; import com.zzq.spring6.iocxml.auto.service.UserService; import com.zzq.spring6.iocxml.auto.service.UserSeviceImpl; public class UserController { private UserService userService; public void setUserService(UserService userService) { this.userService = userService; } public void addUser(){ System.out.println("controller方法执行了"); //调用service的方法 userService.addUserService(); // UserService userService=new UserSeviceImpl(); // userService.addUserService(); } }
package com.zzq.spring6.iocxml.auto.service; public interface UserService { public void addUserService(); }
package com.zzq.spring6.iocxml.auto.service; import com.zzq.spring6.iocxml.auto.dao.UserDao; import com.zzq.spring6.iocxml.auto.dao.UserDaoImpl; public class UserSeviceImpl implements UserService { private UserDao userDao; public void setUserDao(UserDao userDao) { this.userDao = userDao; } @Override public void addUserService() { System.out.println("userService方法执行了"); userDao.addUserDao(); // UserDao userDao=new UserDaoImpl(); // userDao.addUserDao(); } }
package com.zzq.spring6.iocxml.auto.dao; public class UserDaoImpl implements UserDao { @Override public void addUserDao(){ System.out.println("userDao方法执行了"); } }
package com.zzq.spring6.iocxml.auto.dao; import com.zzq.spring6.iocxml.auto.service.UserService; public interface UserDao { public void addUserDao(); }
package com.zzq.spring6.iocxml.auto; import com.zzq.spring6.iocxml.auto.controller.UserController; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUser { public static void main(String[] args) { ApplicationContext context=new ClassPathXmlApplicationContext("bean-auto.xml"); UserController controller = context.getBean("userController", UserController.class); controller.addUser(); } }
自动装配方式:byName
>
> byName:将自动装配的属性的属性名,作为bean的id在IOC容器中匹配相对应的bean进行赋值
情况一:最基本的扫描方式**
```xml
```
**情况二:指定要排除的组件**
```xml
```
**情况三:仅扫描指定组件**
```xml
```
以上四个注解都可实现bean的创建
package com.zzq.bean; import org.springframework.stereotype.Component; import org.springframework.stereotype.Controller; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Service; @Component(value = "user")//属性可不写,默认为user //@Controller //@Repository //@Service public class User { }
单独使用@Autowired注解,**默认根据类型装配**。【默认是byType】
package com.zzq.autowired.controller; import com.zzq.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class UserController { //注入service //第一种方式属性的注入 @Autowired//根据类型找到对应对象,完成注入 private UserService userService; public void add(){ System.out.println("controller..."); userService.add(); } }
package com.zzq.autowired.service; import com.zzq.autowired.dao.UserDao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @Service public class UserServiceImpl implements UserService{ //注入dao //第一种方式属性注入 //@Autowired // private UserDao userDao; //第二种方式set方法注入 // @Autowired // private UserDao userDao; // // public void setUserDao(UserDao userDao) { // this.userDao = userDao; // } //第三种方式:构造方法中注入 private UserDao userDao; @Autowired public UserServiceImpl(UserDao userDao) { this.userDao = userDao; } @Override public void add() { System.out.println("service..."); userDao.add(); } }
package com.zzq.autowired.controller; import com.zzq.autowired.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller public class UserController { //注入service //第一种方式属性的注入 // @Autowired//根据类型找到对应对象,完成注入 // private UserService userService; //第二种方式set方法注入 // private UserService userService; //@Autowired // public void setUserService(UserService userService) { // this.userService = userService; // } //第三种方式 构造方法的注入 // private UserService userService; //@Autowired // public UserController(UserService userService) { // this.userService = userService; // } //第四种方式 private UserService userService; public UserController( @Autowired UserService userService) { this.userService = userService; } public void add(){ System.out.println("controller..."); userService.add(); } }
@Autowired注解可以出现在:属性上、构造方法上、构造方法的参数上、setter方法上。
- 当带参数的构造方法只有一个,@Autowired注解可以省略。()
- @Autowired注解默认根据类型注入。如果要根据名称注入的话,需要配合@Qualifier注解一起使用。
@Resource注解也可以完成属性注入。那它和@Autowired注解有什么区别?
- @Resource注解是JDK扩展包中的,也就是说属于JDK的一部分。所以该注解是标准注解,更加具有通用性。(JSR-250标准中制定的注解类型。JSR是Java规范提案。)
- @Autowired注解是Spring框架自己的。
- **@Resource注解默认根据名称装配byName,未指定name时,使用属性名作为name。通过name找不到的话会自动启动通过类型byType装配。**
- **@Autowired注解默认根据类型装配byType,如果想根据名称装配,需要配合@Qualifier注解一起用。**
- @Resource注解用在属性上、setter方法上。
- @Autowired注解用在属性上、setter方法上、构造方法上、构造方法参数上。
@Resource注解属于JDK扩展包,所以不在JDK当中,需要额外引入以下依赖:【**如果是JDK8的话不需要额外引入依赖。高于JDK11或低于JDK8需要引入以下依赖。**】
jakarta.annotation jakarta.annotation-api 2.1.1
package com.zzq.resource.controller; import com.zzq.resource.service.UserService; import jakarta.annotation.Resource; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; @Controller("myUserController") public class UserController { //根据名称进行注入 //@Resource(name = "myUserService") //private UserService userService; //根据类型进行注入 @Resource private UserService userService; public void add(){ System.out.println("controller..."); userService.add(); } }
package com.zzq.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; @Configuration//配置类 @ComponentScan("com.zzq")//开启组件扫描 public class SpringConfig { }
package com.zzq.resource; import com.zzq.config.SpringConfig; import com.zzq.resource.controller.UserController; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestUserControllerAnno { public static void main(String[] args) { //加载配置类 ApplicationContext context= new AnnotationConfigApplicationContext(SpringConfig.class); UserController controller = context.getBean(UserController.class); controller.add(); } }
package com.zzq; import org.junit.jupiter.api.Test; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; public class TestCar { //1、获取clas对象多种方式 @Test public void test01() throws Exception { //1、类名.class Class clazz1 = Car.class; //2、对象.getclass() Class clazz2 = new Car().getClass(); //3、Class.forname("全路径") Class clazz3 = Class.forName("com.zzq.Car"); //实例化 Car car = (Car) clazz3.getDeclaredConstructor().newInstance(); System.out.println(car); } //2、通过反射获取构造方法 @Test public void test02() throws Exception { Class clazz = Car.class; //获取所有构造 Constructor[] constructors = clazz.getConstructors(); for (Constructor c : constructors) { System.out.println("方法个数" + c.getName() + "参数个数" + c.getParameterCount()); } //指定有参数构造创建对象 //1、构造public // Constructor c1=clazz.getConstructor(String.class,int.class, String.class); // Car car1 = (Car)c1.newInstance("本部", 10, "黄色"); // System.out.println(car1); //2、构造private Constructor c2 = clazz.getDeclaredConstructor(String.class, int.class, String.class); c2.setAccessible(true); Car car2 = (Car) c2.newInstance("部", 11, "黄色"); System.out.println(car2); } //3、获取属性 @Test public void test03() throws Exception { Class clazz = Car.class; //实例化 Car car = (Car) clazz.getDeclaredConstructor().newInstance(); //获取所有的public属性 // Field[]fields=clazz.getFields(); //获取所有属性(包含私有属性) Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { if (field.getName().equals("name")) { field.setAccessible(true); field.set(car, "奥迪"); } System.out.println(field.getName()); System.out.println(car); } } //4、获取方法 @Test public void test04() throws Exception { Car car=new Car("宝马",19,"黑色"); Class clazz=car.getClass(); //public方法 Method[]methods=clazz.getMethods(); for (Method m1:methods ) { // System.out.println(m1.getName()); //执行方法toString if (m1.getName().equals("toString")){ String invoke=(String) m1.invoke(car); // System.out.println("toString执行了:"+invoke); } //private方法 Method[] methodsAll = clazz.getDeclaredMethods(); for (Method m:methodsAll){ if (m.getName().equals("run")){ m.setAccessible(true); m.invoke(car); } } } } }
ApplicationContext.java
package com.zzq.Bean; import com.zzq.anno.Bean; public interface ApplicationContext { Object getBean(Class clazz); }
AnnotationApplicationContext.java
package com.zzq.Bean; import com.zzq.anno.Bean; import com.zzq.anno.Di; import java.io.File; import java.lang.reflect.Field; import java.net.URL; import java.net.URLDecoder; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Set; public class AnnotationApplicationContext implements ApplicationContext { //创建map集合,放bean对象 private Map beanFactory = new HashMap<>(); private static String rootPath; //返回对象 @Override public Object getBean(Class clazz) { return beanFactory.get(clazz); } //设置包扫描规则 //当前包及其子包,拿个类有@Bean注解,把这个类通过反射实例化 public AnnotationApplicationContext(String basePackage) { // public static void pathdemo1(String basePackage) { //把.替换成\ try { String packagePath = basePackage.replaceAll("\\.", "\\\\"); //获取包绝对路径 Enumeration urls = Thread.currentThread().getContextClassLoader().getResources(packagePath); while (urls.hasMoreElements()) { URL url = urls.nextElement(); String filePath = URLDecoder.decode(url.getFile(), "utf-8"); //获取包前面路径得到部分,字符串截取 rootPath = filePath.substring(0, filePath.length() - packagePath.length()); //包扫描 loadBean(new File(filePath)); } } catch (Exception e) { throw new RuntimeException(e); } //属性得到注入 loadDi(); } // //包扫描的过程,实例化 private void loadBean(File file) throws Exception { //1、判断当前是否文件夹 if (file.isDirectory()) { //2、获取文件夹里面所有内容 File[] childrenFiles = file.listFiles(); //3、判断文件夹里面为空,直接返回 if (childrenFiles == null || childrenFiles.length == 0) { return; } //4、如果文件夹里面不为空,遍历文件夹所有内容 for (File child : childrenFiles) { //4.1遍历得到某个File对象,继续判断,如果还是文件, if (child.isDirectory()) { //递归 loadBean(child); } else { //4.2遍历得到File对象不是文件夹,是文件 //4.3得到包路径+类名称部分-字符串截取 String pathWithClass = child.getAbsolutePath().substring(rootPath.length() - 1); //4.4判断当前文件类型是否.class if (pathWithClass.contains(".class")) { //4.5如果是.class类型,把路径\替换. 把class去掉 String allName = pathWithClass.replaceAll("\\\\", ".") .replace(".class", ""); //4.6判断类上面是否有注解@Bean,如果有实例化过程 //4.6.1获取类发class Class> clazz = Class.forName(allName); //4.6.2判断不是接口 if (!clazz.isInterface()) { //4.6.3判断类上面是否有注解@Bean Bean annotation = clazz.getAnnotation(Bean.class); if ((annotation != null)) { //4.6.4实例化 Object instance = clazz.getConstructor().newInstance(); //4.7把对象实例化之后,放到map集合beanFactory //4.7.1判断当前类如果有接口,让接口class作为map的key if (clazz.getInterfaces().length > 0) { beanFactory.put(clazz.getInterfaces()[0], instance); } else { beanFactory.put(clazz, instance); } } } } } } } } //属性注入 private void loadDi() { //实例化对象在beanFactory的map集合里面 //1、遍历beanFactory的map集合 Set>entries=beanFactory.entrySet(); for (Map.Entryentry:entries) { //2、获取map集合每个对象(value),每个对象属性获取到 Object obj=entry.getValue(); //获取对象Class Class> clazz=obj.getClass(); //获取每个对象的属性 Field[] declaredFields = clazz.getDeclaredFields(); //遍历得到每个对象属性数组,得到每个属性 for (Field field:declaredFields) { //4、判断属性上面是否有@Di注解 Di annotation = field.getAnnotation(Di.class); if (annotation != null) { //如果私有属性,设置可以设置值 field.setAccessible(true); //5、如果有@Di注解,把对象进行设置(注入) try { field.set(obj, beanFactory.get(field.getType())); }catch (IllegalAccessException e){ throw new RuntimeException(e); } } } } } }
package com.zzq.anno; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Bean { }
package com.zzq.anno; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target({ElementType.FIELD}) @Retention(RetentionPolicy.RUNTIME) public @interface Di { }
package com.zzq; import com.zzq.Bean.AnnotationApplicationContext; import com.zzq.Bean.ApplicationContext; import com.zzq.service.UserService; public class TestUser { public static void main(String[] args) { ApplicationContext context= new AnnotationApplicationContext("com.zzq"); UserService userService = (UserService)context.getBean(UserService.class); System.out.println(userService); userService.add(); } }