这里要先了解Bean的后置处理器(BeanProstProcessor):
我们可以理解为大多数情况下在创建了对象之后,可以进行对对象的其他操作,再转化成Bean
@Component public class FactoryBeanProstProcessor implements BeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { return null; } public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { return null; } }
使用后置处理找到对应类中属性的注解
就相当于对这个对象进行处理(赋值等等...)
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface LuoLuo { String value(); } @ComponentScan("com.test")//扫描路径 public class Config { } @Component public class FactoryBeanProstProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { Class<?> clazz = bean.getClass(); for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(LuoLuo.class)){ LuoLuo fieldAnnotation = field.getAnnotation(LuoLuo.class);//得到这个属性上的注解 String s = fieldAnnotation.value();//讲注解赋值给s System.out.println(s); } } return null; } } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);//通过Config配置得到对象 UserService userService = (UserService) context.getBean("userService"); System.out.println(userService); } 最后输出 xiaoluoxxx
实例化
@ComponentScan("com.user") public class Config { } @Component public class UserService { public UserService() { System.out.println("我是无参构造"); } } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); UserService userService = context.getBean("userService", UserService.class); System.out.println(userService); } 我是无参构造 com.user.UserService@42607a4f
实例化前
@Component public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor { public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("实例化前"); } return null; } 实例化前 我是无参构造 com.user.UserService@6fb0d3ed
如果实例化前给他直接返回一个对象,那么就不会再进行实例化
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("实例化前"); } return new UserService(); }
实例化和推断构造方法
@Component public class UserService { private User user; public UserService(User user) { this.user=user; System.out.println("一个有参构造"); } } 只有一个有参构造就直接调用 一个有参构造 @Component public class UserService { private User user; public UserService(User user) { this.user=user; System.out.println("一个有参构造"); } @Autowired//必须的必要的 public UserService(User user,User user1) { this.user=user; System.out.println("二个有参构造"); } 二个有参构造 有两个有参就会报错,但是只要给他一个注解,他就会自动判断有注解的哪一个 @Autowired(required = false) public UserService(User user) { this.user=user; System.out.println("一个有参构造"); } @Autowired(required = false) public UserService(User user,User user1) { this.user=user; System.out.println("二个有参构造"); } 按照自己的逻辑会选一个构造方法会先选参数多的 如果一样多就会按顺序选择.
实例化后
@Component public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor { public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { return null; } public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("我是后置"); } return true; } } @Component public class UserService { private User user; public UserService() { System.out.println("我是无参构造方法"); } @Autowired public void setUser(User user) { System.out.println("set方法注入"); this.user = user; } } 我是无参构造方法 我是后置 set方法注 我们可以在实例化后操作这个对象的属性
初始化
@Component public class UserService implements InitializingBean { private User user; public UserService() { System.out.println("我是无参构造方法"); } @Autowired public void setUser(User user) { System.out.println("set方法注入"); this.user = user; } public void afterPropertiesSet() throws Exception { System.out.println("初始化"); } } 我是无参构造方法 我是后置 set方法注入 初始化 @Component public class UserService implements InitializingBean { private User user; @PostConstruct public void xxx(){ System.out.println("xxx"); } public UserService() { System.out.println("我是无参构造方法"); } @Autowired public void setUser(User user) { System.out.println("set方法注入"); this.user = user; } public void afterPropertiesSet() throws Exception { System.out.println("初始化"); } } 我是无参构造方法 我是后置 set方法注入 xxx 初始化 @PostConstruct 利用初始化前的这个注解,可以进行其他操作 <dependency> <groupId>javax.annotation</groupId> <artifactId>javax.annotation-api</artifactId> <version>1.3.2</version> </dependency>
初始化会在Spring自动注入后面才会执行,我们可以在里面修改我们想修改的都可以
初始化前
@PostConstruct public void xxx(){ System.out.println("xxx"); } @Component public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("初始化前"); } return null; } } 我是无参构造方法 set方法注入 初始化前 初始化 com.user.UserService@3439f68d @Component public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("初始化前"); } return bean; } } 我是无参构造方法 set方法注入 初始化前 xxx 初始化 com.user.UserService@3439f68d
这里我们的xxx方法上面的注解就相当于一个postProcessBeforeInitialization
LLBeanPostProcess------>postProcessBeforeInitialization 当方法返回null时,这里就起到一个中断的作用,前面的实例化全部都做完了,如果返回一个bean对象,初始化前方法就会把bean对象传到下一个方法中!
@PostConstruct------>postProcessBeforeInitialization 前面有对象返回的时候才有效!
验证 @Component public class LLBeanPostProcess implements InstantiationAwareBeanPostProcessor { public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("初始化前"); for (Method method : bean.getClass().getMethods()) { if (method.isAnnotationPresent(PostConstruct.class)){ try { method.invoke(bean);//如果这个方法上面有这个注解就再执行一次 } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } } } } return bean; } } 我是无参构造方法 set方法注入 初始化前 xxx xxx 初始化 com.user.UserService@3439f68d
初始化后
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ System.out.println("初始化后"); } return bean; } 我是无参构造方法 set方法注入 初始化前 xxx xxx 初始化 初始化后 com.user.UserService@3439f68d
我们就可以在这里面进行多态代理,也就是AOP,下面我们来进行一下模拟
package com.user; public interface UserInterface { public void test(); } public class UserService implements InitializingBean ,UserInterface{ public void test() { System.out.println("业务逻辑"); } } public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ Object o = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object o, Method method, Object[] objects) throws Throwable { System.out.println("动态代理"); return null; } }); return o; } return bean; } public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class); UserInterface userService = (UserInterface) context.getBean("userService"); userService.test(); } 我是无参构造方法 set方法注入 初始化前 xxx xxx 初始化 动态代理 //这个bean就时userService对象,我们在初始化后方法中可以讲这个bean对象替换掉,替换成我们这个动态代理的代理类,相当于狸猫换太子。我们想要先执行我们的代理逻辑,再执行传入的userService对象的对应的method方法。 public Object postProcessAfterInitialization(final Object bean, String beanName) throws BeansException { if (beanName.equals("userService")){ Object o = Proxy.newProxyInstance(bean.getClass().getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() { public Object invoke(Object o, Method method, Object[] objects) throws Throwable { System.out.println("代理逻辑1"); method.invoke(bean,objects); System.out.println("代理逻辑2"); return null; } }); return o; } return bean; } 我是无参构造方法 set方法注入 初始化前 xxx xxx 初始化 代理逻辑1 业务逻辑 代理逻辑2
也是我们Spring实现aop的基本逻辑。