测试类
public class TestMain {
public static void main(String[] args) throws Exception {
//1.声明注册bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("teacher");
beanObj.setClassPath("com.kaikeba.beans.Teacher");
//beanObj.setScope("prototype"); //根据spring框架介绍,默认情况下就是单例的singleton
List beanList = new ArrayList();
beanList.add(beanObj);//spring核心配置
//2.声明一个Spring提供BeanFacotory
BeanFactory factory = new BeanFactory(beanList);
//3.开发人员向BeanFactory索要实例对象.
Teacher t= (Teacher) factory.getBean("teacher");
System.out.println("t="+t);
Teacher t2= (Teacher) factory.getBean("teacher");
System.out.println("t2="+t2);
}
}
BeanFactory类,用于解析传入的beanId和创建实例对象
public class BeanFactory {
private List<BeanDefined> beanDefinedList;
private Map<String ,Object> SpringIoc;//已经创建好实例对象
public List<BeanDefined> getBeanDefinedList() {
return beanDefinedList;
}
public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
this.beanDefinedList = beanDefinedList;
SpringIoc = new HashMap(); //所有scope="singleton" 采用单类模式管理bean对象
for(BeanDefined beanObj:this.beanDefinedList){
if("singleton".equals(beanObj.getScope())){
Class classFile= Class.forName(beanObj.getClassPath());
Object instance= classFile.newInstance();
SpringIoc.put(beanObj.getBeanId(), instance);
}
}
}
public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
this.beanDefinedList = beanDefinedList;
}
public Object getBean(String beanId) throws Exception{
Object instance = null;
for(BeanDefined beanObj:beanDefinedList){
if(beanId.equals(beanObj.getBeanId())){
String classPath = beanObj.getClassPath();
Class classFile= Class.forName(classPath);
String scope=beanObj.getScope();
if("prototype".equals(scope)){
//.getBean每次都要返回一个全新实例对象
instance= classFile.newInstance();
}else{
instance=SpringIoc.get(beanId);
}
return instance;
}
}
return null;
}
}
public class BeanDefined {
private String beanId;
private String classPath;
private String scope ="singleton";
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public String getBeanId() {
return beanId;
}
public void setBeanId(String beanId) {
this.beanId = beanId;
}
public String getClassPath() {
return classPath;
}
public void setClassPath(String classPath) {
this.classPath = classPath;
}
}
通过这个例子,告诉了我们Spring的核心就是一个工厂类,在配置文件写的这些标签。 实际上只是作者自己定义的规则,规则里面告诉我们如何把java类信息交给当前spring。spring在运行过程中,在默认的场景下就是使用反射工厂来进行创建的
demo里面使用了单例模式去管理bean对象,第一次创建实例对象放到我们的容器中,第二次去IOC容器依靠beanId去获取创建好的单例对象
好处: 不同的用户,对相同对象创建时有不同的要求,修改完成后只需要修改配置文件就可以了,需要对我们工程的类进行重新的编译。
ps:为了节省内存消耗,也可以用静态工厂的方式,静态工厂只需要在类名前面加static就可以了。配置文件也不需要再去加载class的路径。
定义: 在bean对象创建之后,对它的某些行为进行拦截,所拦截行为的功能做一个相关的增强操作,叫做bean后处理器。
bean的后置处理器的出现暴露出了spring的作者真正的目的,spring真正想给我们的是bean的代理对象。而不是单纯的new 对象。
代理就是对行为的一种监控,能体现行为的就是接口,想要好用,必须要接口来修饰
//需要被代理的接口
public interface BaseService {
public String doSome();
}
//需要被代理的接口的实现类
public class ISomeService implements BaseService {
public String doSome() {
// TODO Auto-generated method stub
return "Hello mike";//增强效果,doSome方法返回值都是大写
}
}
完成类注册
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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:被监控实现类 -->
<bean id="isomeService" class="com.kaikeba.serviceImpl.ISomeService"></bean>
<!-- 注册代理实现类 -->
<bean class="com.kaikeba.util.MyBeanPostProcessor"></bean>
</beans>
//bean为当前的实例对象。beanName为当前bean的名称
public class MyBeanPostProcessor implements BeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) throws Exception
System.out.println("bean对象初始化之前。。。。。");
return bean;l
//return bean对象监控代理对象
}
public Object postProcessAfterInitialization(final Object beanInstance, String beanName) throws Exception {
// 为当前bean对象注册代理监控对象,负责增强bean对象方法能力
Class beanClass = beanInstance.getClass();
if (beanClass == ISomeService.class) {
/*
*
*beanInstance.getClass().getClassLoader()当前类对象的类文件
*beanInstance.getClass().getInterfaces()拦截对象的行为
*new InvocationHandler()new反射机制包的接口(接口作为内置对象的时候是可以new的
**/
Object proxy = Proxy.newProxyInstance(beanInstance.getClass().getClassLoader(),
beanInstance.getClass().getInterfaces(), new InvocationHandler() {
/*
*
* method:doSome(需要拦截的方法) args:doSome执行接受实参 proxy:代理监控对对象
**/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("ISomeService doSome 被拦截");
String result = (String) method.invoke(beanInstance, args);// beanInstance.doSome
return result.toUpperCase();
}
});
return proxy; //返回代理监控对象
}
return beanInstance;
}
测试一下,最终输出的信息变成了大写
public class TestMain {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("spring_config.xml");
//向spring工厂获取代理类的bean,代理就是对行为的一种监控,能体现行为的就是接口,想要好用,必须要接口来修饰
BaseService serviceObj = (BaseService) factory.getBean("isomeService");
System.out.println(serviceObj.doSome());
}
}
小知识:实例化指的是去创建这个类的实例对象。初始化是对当前实例对象的相关属性做处理。
抛出问题:spirng容器的实质就是一个工厂,是帮助我们创造对象的。如果spring容器关闭,那它所创建的bean对象是不是就会消亡呢?
答案是:并不会,在java的世界中,对象什么时候被干掉是有依据的,例如一个bean对象,早期是由spring框架的工厂类创建的,最终这个对象是要交给我们的开发人员的。开发人员也会去创建一个相关的引用对象,这个引用对象也指向它。所以bean对象还有其他的引用对象,所以创建的bean对象是不会消亡的
public class BeanFactory {
//private List beanDefinedList;
//private Map SpringIoc;//已经创建好实例对象
private BeanPostProcessor processorObj;//增加后置对象
//public List getBeanDefinedList() {
//return beanDefinedList;
//}
//public BeanFactory(List beanDefinedList) throws Exception {
//this.beanDefinedList = beanDefinedList;
//SpringIoc = new HashMap(); //所有scope="singleton" 采用单类模式管理bean对象
//for(BeanDefined beanObj:this.beanDefinedList){
//if("singleton".equals(beanObj.getScope())){
//Class classFile= Class.forName(beanObj.getClassPath());
//Object instance= classFile.newInstance();
//判断当前对象是一个bean对象还是后置处理处理对象
isProcessor(instance,classFile);
SpringIoc.put(beanObj.getBeanId(), instance);
}
}
}
//传入实例对象和所关联的类文件
private void isProcessor(Object instance,Class classFile){
//查看类文件实现的接口,可能有多个接口,用数组去接收
Class interfaceArray[] = classFile.getInterfaces();
//判空
if(interfaceArray==null){
return;
}
for(int i=0;i<interfaceArray.length;i++){
Class interfaceType = interfaceArray[i];
//所有的后置处理对象都需要实现BeanPostProcessor
//判断这个接口类型是不是BeanPostProcessor.class
if(interfaceType == BeanPostProcessor.class){
//证明当前实例对象是后置处理器
this.processorObj = (BeanPostProcessor)instance;
}
}
}
//public Object getBean(String beanId) throws Exception{
//Object instance = null;
Object proxyObj = null;//当前实例对象的代理监控对象
//for(BeanDefined beanObj:beanDefinedList){
//if(beanId.equals(beanObj.getBeanId())){
//String classPath = beanObj.getClassPath();
//Class classFile= Class.forName(classPath);
//String scope=beanObj.getScope();
//String factoryBean = beanObj.getFactoryBean();
//String factoryMehtod=beanObj.getFactoryMethod();
//if("prototype".equals(scope)){//.getBean每次都要返回一个全新实例对象
//if(factoryBean!=null && factoryMehtod!=null){//用户希望使用指定工厂创建实例对象
//Object factoryObj= SpringIoc.get(factoryBean);
//Class factoryClass=factoryObj.getClass();
// Method methodObj= //factoryClass.getDeclaredMethod(factoryMehtod, null);
//methodObj.setAccessible(true);
//instance= methodObj.invoke(factoryObj, null);
//}else{
// instance= classFile.newInstance();
//}
//}else{
//instance=SpringIoc.get(beanId);
//}
//前置,传入实例对象和所关联的ID
if(this.processorObj!=null){
proxyObj = this.processorObj.postProcessBeforeInitialization(instance, beanId);
//实例对象初始化。Spring依赖注入
proxyObj = this.processorObj.postProcessAfterInitialization(instance, beanId);
//此时返回proxyObj可能就是原始bean对象,也有可能就是代理对象
return proxyObj;
}else{
return instance;
}
}
}
return null;
}
}
测试一下
public class TestMain {
public static void main(String[] args) throws Exception {
//1.声明注册bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("isomeService");
beanObj.setClassPath("com.kaikeba.serviceImpl.ISomeService");
BeanDefined beanObj2 = new BeanDefined();
beanObj2.setClassPath("com.kaikeba.util.MyBeanPostProcessor");
List configuration = new ArrayList();
configuration.add(beanObj);//spring核心配置
configuration.add(beanObj2);
//2.声明一个Spring提供BeanFacotory
BeanFactory factory = new BeanFactory(configuration);
//3.开发人员向BeanFactory索要实例对象.
BaseService t= (BaseService) factory.getBean("isomeService");
System.out.println("t="+t);
System.out.println(t.doSome());//HELLO MIKE
}
}
上面都是sping 容器对bean对象实例化的过程,未涉及初始化。
初始化的过程我们把它称为依赖注入,依赖工厂为对象中属性赋值处理,叫做依赖注入。
ps:个人认为依赖注入是spring里面最简单得知识点,只要学习过反射,这个事情就不难。
完成依赖注入配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
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="teacher" class="com.kaikeba.beans.Teacher">
<property name="teacherName" value="Mr Luo"></property>
<property name="friendArray" value="mike,allen,tom"></property>
<property name="school" value="杭州测试、杭州java开发、杭州前端开发"></property>
</bean>
</beans>
测试
public class TestMain {
public static void main(String[] args) {
ApplicationContext factory = new ClassPathXmlApplicationContext("spring_config.xml");
Teacher teacher = (Teacher) factory.getBean("teacher");
System.out.println(teacher.getTeacherName());
System.out.println(teacher.getFriendArray());
System.out.println(teacher.getSchool());
//分别打印出xml配置文件中的value
}
}
这个类相当于xml管理得标签
@Data
public class BeanDefined {
/*
*
* 这个类相当于xml管理得标签
*
**/
private String beanId;
private String classPath;
private String scope ="singleton";
private String factoryBean=null;
private String factoryMethod=null;
private Map<String,String> propertyMap=new HashMap();
}
依赖注入得实现
public class BeanFactory {
private List<BeanDefined> beanDefinedList;
private Map<String ,Object> SpringIoc;//已经创建好实例对象
private BeanPostProcessor processorObj;//后置对象
public List<BeanDefined> getBeanDefinedList() {
return beanDefinedList;
}
//依赖注入(传入实例对象、实例对象关联的类文件、propertyMap)
public void setValue(Object instance,Class classFile,Map propertyMap) throws NoSuchFieldException, SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//循环遍历 propertyMap<属性名,属性值>
//获取类的所有方法
Method methodArray[]= classFile.getDeclaredMethods();
//获取所有的key
Set fieldNameSet = propertyMap.keySet();
Iterator fieldIterator = fieldNameSet.iterator();
while(fieldIterator.hasNext()){
//拿到属性名
String fieldName = (String) fieldIterator.next();
//拿到对应的value
String value = (String) propertyMap.get(fieldName);
Field fieldObj = classFile.getDeclaredField(fieldName);//同名属性对象(字段)
for(int i=0;i<methodArray.length;i++){
//分别获取类的方法对象
Method methodObj = methodArray[i];
String methodName ="set"+fieldName;// sid == setsid
if(methodName.equalsIgnoreCase(methodObj.getName())){
//配置文件全写成string了,实际上很多不是,要判断一下
//获取属性的数据类型 Integer,String,Double,boolean,list
Class fieldType= fieldObj.getType();
//分别判断
if(fieldType == String.class){
methodObj.invoke(instance, value);
}else if(fieldType == Integer.class){
methodObj.invoke(instance, Integer.valueOf(value));
}else if(fieldType == Boolean.class){
methodObj.invoke(instance, Boolean.valueOf(value));
}else if(fieldType==List.class){
List tempList = new ArrayList();
//value以逗号分隔,全部取出交给数组
String dataArray[]=value.split(",");
for(int j=0;j<dataArray.length;j++){
tempList.add(dataArray[j]);
}
methodObj.invoke(instance, tempList);
}else{
//此时属性类型是数组
String dataArray[]=value.split(",");
//设置方法实参是一个
Object data[] = new Object[1];
data[0]=dataArray;
methodObj.invoke(instance, data);
}
break;
}
}
}
}
public BeanFactory(List<BeanDefined> beanDefinedList) throws Exception {
this.beanDefinedList = beanDefinedList;
SpringIoc = new HashMap(); //所有scope="singleton" 采用单类模式管理bean对象
for(BeanDefined beanObj:this.beanDefinedList){
if("singleton".equals(beanObj.getScope())){
Class classFile= Class.forName(beanObj.getClassPath());
Object instance= classFile.newInstance();
//判断当前对象是一个bean对象还是后置处理处理对象
isProcessor(instance,classFile);
SpringIoc.put(beanObj.getBeanId(), instance);
}
}
}
private void isProcessor(Object instance,Class classFile){
//getInterfaces()方法获得这个对象所实现的接口。
Class interfaceArray[] = classFile.getInterfaces();
if(interfaceArray==null){
return;
}
for(int i=0;i<interfaceArray.length;i++){
Class interfaceType = interfaceArray[i];
if(interfaceType == BeanPostProcessor.class){
//证明当前实例对象是后置处理器
this.processorObj = (BeanPostProcessor)instance;
}
}
}
public void setBeanDefinedList(List<BeanDefined> beanDefinedList) {
this.beanDefinedList = beanDefinedList;
}
public Object getBean(String beanId) throws Exception{
Object instance = null;
Object proxyObj = null;//当前实例对象的代理监控对象
for(BeanDefined beanObj:beanDefinedList){
if(beanId.equals(beanObj.getBeanId())){
String classPath = beanObj.getClassPath();
Class classFile= Class.forName(classPath);
String scope=beanObj.getScope();
String factoryBean = beanObj.getFactoryBean();
String factoryMehtod=beanObj.getFactoryMethod();
Map propertyMap = beanObj.getPropertyMap();
if("prototype".equals(scope)){
//.getBean每次都要返回一个全新实例对象
if(factoryBean!=null && factoryMehtod!=null){
//用户希望使用指定工厂创建实例对象
Object factoryObj= SpringIoc.get(factoryBean);
Class factoryClass=factoryObj.getClass();
Method methodObj= factoryClass.getDeclaredMethod(factoryMehtod, null);
methodObj.setAccessible(true);
instance= methodObj.invoke(factoryObj, null);
}else{
instance= classFile.newInstance();
}
}else{
instance=SpringIoc.get(beanId);
}
if(this.processorObj!=null){
proxyObj = this.processorObj.postProcessBeforeInitialization(instance, beanId);
//实例对象初始化。Spring依赖注入
setValue(instance,classFile,propertyMap);
proxyObj = this.processorObj.postProcessAfterInitialization(instance, beanId);
//此时返回proxyObj可能就是原始bean对象,也有可能就是代理对象
return proxyObj;
}else{
//实例对象初始化
setValue(instance,classFile,propertyMap);
return instance;
}
}
}
return null;
}
}
测试类
public class TestMain {
public static void main(String[] args) throws Exception {
//1.声明注册bean
BeanDefined beanObj = new BeanDefined();
beanObj.setBeanId("teacher");
beanObj.setClassPath("com.kaikeba.beans.Teacher");
/*
*
*
**/
Map<String, String> propertyMap = beanObj.getPropertyMap();
propertyMap.put("teacherName", "李老师");
propertyMap.put("friendArray", "老刘,老孙,小师妹");
propertyMap.put("school", "清华一小,北京理工大学");
List configuration = new ArrayList();
configuration.add(beanObj);//spring核心配置
//2.声明一个Spring提供BeanFacotory
BeanFactory factory = new BeanFactory(configuration);
//3.开发人员向BeanFactory索要实例对象.
Teacher t= (Teacher) factory.getBean("teacher");
System.out.println("t="+t);
//打印出初始化数据
System.out.println(t.getTeacherName());
}
}
AOP即代理设计模式实现细节:用较少的代码实现一个简单的代理模式
如果不用AOP,实现一个代理模式需要实现的步骤
Spring AOP:简化代理模式实现步骤
说白了就是次要业务
当前需要监控的某个实例对象