Spring IOC容器

IOC底层原理

主要用到的技术

xml解析、工厂模式、反射

IOC接口BeanFactory

1、IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
2、Spring提供IOC容器实现的两种方式:(两个接口)
(1)、BeanFactory:IOC容器基本实现,是spring内部的使用接口,不提倡开发人员使用
特点:加载配置文件的时候不会创建对象,在获取对象(使用才去创建对象)
(2)、ApplicationContext:BeanFactory接口的子接口,提供更多更强大的功能,一般由开发人员使用
特点:加载配置文件的时候会把在配置文件配置的对象进行创建
(3)、ApplicationContext接口的两个实现类:

在这里插入图片描述

IOC操作Bean管理(基于xml)

1、什么是Ben管理
Bean管理指的两个操作:

(1)、Spring创建对象
在Spring配置文件中,使用bean标签,标签中添加对应属性,就可以创建对象,下面介绍常用的
id属性:唯一标识
class属性:类的全限定类名
创建对象时,默认是执行无参构造方法
(2)、Spring注入属性
set注入

 <bean id="user" class="com.yun.User">
     <property name="nickname" value="张三"/>
     <property name="password" value="123456"/>
</bean>

有参构造注入

<bean id="user" class="com.yun.User">
    <constructor-arg name="nickname" value="猪八戒" type="java.lang.String"/>
    <constructor-arg name="password" value="zhubajie" type="java.lang.String"/>
</bean>

P名称空间注入(可以简化xml配置)
导入约束:
在这里插入图片描述

<beans>
        <bean id="user" class="com.yun.User" p:nickname="孙悟空" p:password="sunwukong"/>
    </beans>

注入null值和特殊符号

<beans>
    <bean id="user" class="com.yun.User">
        <property name="nickname" value="张三"/>
        <property name="password" value="123456"/>
        <property name="address">
            <null/>
        </property>
    </bean>
</beans>
<beans>
    <bean id="user" class="com.yun.User">
        <property name="nickname" value="张三"/>
        <property name="password" value="123456"/>
        <property name="address">
            <value><![CDATA[<<重庆市渝北区>>]]></value>
        </property>
    </bean>
</beans>

注入属性-外部bean

<bean name="userDaoImpl" class="com.yun.dao.UserDaoImpl"/>

<bean name="userService" class="com.yun.service.UserService">
   <property name="userDao" ref="userDaoImpl"/>
</bean>

注入属性-内部bean

<beans>
    <bean id="emp" class="com.yun.bean.Emp">
        <property name="ename" value="jack"/>
        <property name="sex" value="23"/>
        <property name="dept">
            <bean id="dept" class="com.yun.bean.Dept">
                <property name="dname" value="研发部"/>
            </bean>
        </property>
    </bean>
</beans>

注入属性-级联赋值

第一种方式
<beans>
    <bean id="emp" class="com.yun.bean.Emp">
        <property name="ename" value="jack"/>
        <property name="sex" value="23"/>
        <!--级联赋值-->
        <property name="dept" ref="dept"/>
    </bean>
    
    <bean id="dept" class="com.yun.bean.Dept">
        <property name="dname" value="运营部"/>
    </bean>
</beans>

第二种方式
<beans>
    <bean id="emp" class="com.yun.bean.Emp">
        <property name="ename" value="jack"/>
        <property name="sex" value="23"/>
        <!--级联赋值-->
        <property name="dept" ref="dept"/>
        <property name="dept.dname" value="人事部"/>
    </bean>

    <bean id="dept" class="com.yun.bean.Dept"/>
</beans>

注入数组、List、Map、Set类型属性

<beans>
    <bean id="stu" class="com.yun.bean.Stu">
    <!--注入数组属性-->
        <property name="sourses">
            <array>
                <value type="java.lang.String">123</value>
                <value type="java.lang.String">456</value>
                <value type="java.lang.String">789</value>
            </array>
        </property>
        <!--注入List属性-->
        <property name="lists">
            <list value-type="java.lang.String">
                <value>jack</value>
                <value>lusi</value>
                <value>lili</value>
            </list>
        </property>
        <!--注入Map属性-->
        <property name="maps">
            <map key-type="java.lang.String" value-type="java.lang.String">
                <entry key="m1" value="m_1"/>
                <entry key="m2" value="m_2"/>
                <entry key="m3" value="m_3"/>
            </map>
        </property>
        <!--注入Set属性-->
        <property name="sets">
            <set value-type="java.lang.String">
                <value>23</value>
                <value>21</value>
                <value>19</value>
                <value>193</value>
                <value>223</value>
            </set>
        </property>
    </bean>
</beans>

在List集合中设置对象类型值

    <beans>
        <bean id="stu" class="com.yun.bean.Stu">
        <!--注入数组属性-->
            <property name="sourses">
                <array>
                    <value type="java.lang.String">123</value>
                    <value type="java.lang.String">456</value>
                    <value type="java.lang.String">789</value>
                </array>
            </property>
            <!--注入List属性-->
            <property name="lists">
                <list value-type="java.lang.String">
                    <value>jack</value>
                    <value>lusi</value>
                    <value>lili</value>
                </list>
            </property>
            <!--注入Map属性-->
            <property name="maps">
                <map key-type="java.lang.String" value-type="java.lang.String">
                    <entry key="m1" value="m_1"/>
                    <entry key="m2" value="m_2"/>
                    <entry key="m3" value="m_3"/>
                </map>
            </property>
            <!--注入Set属性-->
            <property name="sets">
                <set value-type="java.lang.String">
                    <value>23</value>
                    <value>21</value>
                    <value>19</value>
                    <value>193</value>
                    <value>223</value>
                </set>
            </property>

            <!--注入list集合类型,值是对象-->
            <property name="courseList">
                <list>
                    <ref bean="course1"/>
                    <ref bean="course2"/>
                </list>
            </property>
        </bean>

        <!-- list集合中的对象 -->
        <bean id="course1" class="com.yun.bean.Course">
            <property name="cname" value="spring框架"/>
        </bean>
        <bean id="course2" class="com.yun.bean.Course">
            <property name="cname" value="Mybatis框架"/>
        </bean>
    </beans>

把List注入部分提前出来

<!-- 提取list集合类型属性注入  -->
    <util:list id="bookList">
        <value>平凡的世界</value>
        <value>时间简史</value>
        <value>十万个为什么</value>
    </util:list>
    <!-- 提取list集合类型属性注入使用  -->
    <beans>
        <bean id="book" class="com.yun.bean.Book">
            <property name="lists" ref="bookList"/>
        </bean>

    </beans>

IOC操作Bean管理

1、Spring有两种bean,一种是普通bean,另一种是工厂bean(FactoryBean)
2、普通bean:在配置文件中定义什么类型的bean就返回什么类型的bean
3、工厂bean:在配置文件中定义bean类型可能跟返回类型不一样
第一步创建类,并实现接口FactoryBean
第二部实现接口里面的方法,在实现的方法中定义返回的bean类型

IOC操作Bean管理(bean的作用域)

1、在Spring里面,设置创建bean实例是单实例还是多实例
2、在Spring里面,默认创建的是单实例bean及默认Spring配置文件中,在创建bean时隐式scope=“singleton”
在这里插入图片描述
3、配置多实例
Spring配置文件中,在创建bean时指定scope=“prototype”即可
在这里插入图片描述
在这里插入图片描述
4、singleton与prototypetype区别
(1)、singleton为单实例、prototype为多实例
(2)、设置scope值为singleon时,加载Spring配置文件时就会创建单实例对象
设置scope值为prototype时,不是在加载Spring配置文件时创建对象,而是在调用getBean方法是创建多实例对象
5、scope的可配值:singleton、prototype、request(每次创建对象时,会把对象放在request中)、session(每次创建对象时,会把对象放在session中)

IOC操作Bean管理(bean的生命周期)

1、什么是生命周期
从对象创建到对象销毁的过程
2、bean生命周期
第一步执行无参构造创建bean实例
第二步调用set方法为对象属性赋值
第三步在初始化之前执行后置处理方法postProcessBeforeInitialization(Object bean, String beanName)
第三步执行初始化方法
第五步在初始化之后执行后置处理方法postProcessAfterInitialization(Object bean, String beanName)
第六步获取对象实例
第七步执行销毁的方法
3、bean生命周期演示
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

IOC操作Bean管理(xml自动装配)

1、什么是自动装配
根据指定装配规则(属性名称或属性类型),Spring自动将匹配的属性值进行注入
2、演示自动装配
在这里插入图片描述

IOC操作Bean管理(xml中引用外部属性文件)

1、直接配置数据库连接信息

<!--直接配置连接池-->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
    <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
    <property name="url" value="jdbc://localhost:3306/userDb"/>
    <property name="username" value="root"/>
    <property name="password" value="root"/>
</bean>

2、引入外部属性文件配置数据库连接池
创建外部属性文件,properties格式文件,写入数据库信息

prop.driverClassName=com.mysql.jdbc.Driver
prop.url=jdbc://localhost:3306/userDb
prop.username=root
prop.password=root
把外部properties属性文件引入到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:context="http://www.springframework.org/schema/context"
       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">
</beans>
<!--引入外部属性文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>
    
<!--配置连接池-->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${prop.driverClassName}"/>
        <property name="url" value="${prop.url}"/>
        <property name="username" value="${prop.username}"/>
        <property name="password" value="${prop.password}"/>
    </bean>

IOC操作Bean管理(基于注解方式)

1、Spring针对Bean管理中创建对象提供的注解
(1)、@Component
(2)、@Service
(3)、@Controller
(4)、@Repository
以上的四个注解功能都是一样的。

AOP底层原理

1、AOP底层使用动态代理(有 两种代理模式)
第一种有接口,使用jdk动态代理
创建接口实现类代理对象,增强类的方法
在这里插入图片描述
第二种没有接口,使用CGLB动态代理
创建子类的代理对象,增强类的方法在这里插入图片描述

AOP(JDK动态代理)

1、使用JDK动态代理,使用Proxy类里面的方法创建代理对象
在这里插入图片描述
调用newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 方法
参数说明:
第一个参数:ClassLoader 类加载器
第二个参数:代理类实现的接口列表
第三个参数:实现这个接口InvocationHandler ,创建代理对象,写增强部分
在这里插入图片描述
2、编写JDK动态代理代码
(1)、创建接口,定义方法

public interface UserDao {
    int add(int a,int b);

    String update(String userId);
}

(2)、创建接口的实现类,实现方法

public class UserDaoImpl implements UserDao {
    @Override
    public int add(int a, int b) {
        System.out.println("执行了add()方法......");
        return a+b;
    }

    @Override
    public String update(String userId) {
        return userId;
    }
}

(3)、使用Proxy类创建接口代理对象

public class JDKProxy {

    public static void main(String[] args) {

        Class[] interfaces = {UserDao.class};

        UserDaoImpl userDaoImpl = new UserDaoImpl();
        UserDao userDao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDaoProxy(userDaoImpl));
        int result = userDao.add(1, 2);
        System.out.println(result);
    }
}

class UserDaoProxy implements InvocationHandler{

    //创建的是谁的代理对象,把谁传过来
    private Object object;

    public UserDaoProxy(Object object) {
        this.object = object;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法执行前
        System.out.println("方法执行前...方法名:"+method.getName()+"::方法参数:"+ Arrays.toString(args));

        //被增强的方法
        Object res = method.invoke(object, args);

        //方法执行后
        System.out.println("方法执行后......"+res);
        return res;
    }
}

运行结果:
在这里插入图片描述

AOP(术语)

1、连接点
类里面那些方法可以被增强,这些方法称为连接点
2、切入点
实例被真正增强的方法,称为切入点
3、通知(增强)
(1)实际增强的逻辑部分称为通知(增强)
(2)通知有多种类型
前置通知 -->方法执行前执行
后置通知 -->方法执行后执行
环绕通知 -->方法执行的前后都执行
异常通知 -->方法执行异常时执行
最终通知 -->同finally
4、切入点表达式
作用:知道对那个类里面的那个方法进行增强
语法结构:
execution([权限修饰符][返回值类型][类的全限定名][方法名称]([参数列表]))
返回值类型可以省略不写、
([参数列表])—> (…):任意个参数
其余可以用 * 号占位 表示全部
5、xml配置

<?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:aop="http://www.springframework.org/schema/aop"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 扫描有@Aspect注解的类 -->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    
    <!-- 开启注解扫描 -->
    <context:component-scan base-package="com.yun.aopanno"></context:component-scan>
</beans>

6、演示实例

@Component
public class User {

    public void add(){
//        int i = 10/0;
        System.out.println("add......");
    }
}
@Component
@Aspect
public class UserProxy {

    //前置通知
    @Before(value = "execution(* com.yun.aopanno.User.add(..))")
    public void before(){
        System.out.println("before.....");
    }

    //最终通知
    @After(value = "execution(* com.yun.aopanno.User.add(..))")
    public void after(){
        System.out.println("after.....");
    }

    //后置通知 在方法有返回值后执行
    @AfterReturning(value = "execution(* com.yun.aopanno.User.add(..))")
    public void afterReturning(){
        System.out.println("afterReturning.....");
    }

    //异常通知
    @AfterThrowing(value = "execution(* com.yun.aopanno.User.add(..))")
    public void afterThrowing(){
        System.out.println("afterThrowing.....");
    }

    //环绕通知
    @Around(value = "execution(* com.yun.aopanno.User.add(..))")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        System.out.println("环绕前.....");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕后.....");
    }
}

7、抽取相同的切入点

@Component
@Aspect
public class UserProxy {

    @Pointcut(value = "execution(* com.yun.aopanno.User.add(..))")
    public void pointDemo(){

    }

    //前置通知
    @Before("pointDemo()")
    public void before(){
        System.out.println("before.....");
    }

    //最终通知
    @After("pointDemo()")
    public void after(){
        System.out.println("after.....");
    }

    //后置通知 在方法有返回值后执行
    @AfterReturning(value = "pointDemo()")
    public void afterReturning(){
        System.out.println("afterReturning.....");
    }

    //异常通知
    @AfterThrowing(value = "pointDemo()")
    public void afterThrowing(){
        System.out.println("afterThrowing.....");
    }

    //环绕通知
    @Around(value = "pointDemo()")
    public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {

        System.out.println("环绕前.....");
        Object proceed = proceedingJoinPoint.proceed();
        System.out.println("环绕后.....");
    }
}

8、有多个增强类对同一个方法进行增强,设置增强类优先级
(1)、在增强类上面添加注解@Order(数字类型值),数字类型值悦小优先级越高

@Component
@Aspect
@Order(1)
public class PersonProxy {
    @Before(value = "execution(* com.yun.aopanno.User.add(..))")
    public void before(){
        System.out.println("Person before......");
    }
}

JdbcTemplate(概论和准备)

1、什么是JdbcTemplate
	(1)、Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库的操作
2、准备工作			
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值