Spring5复习IOC与AOP

1.AOP:控制反转,把创建对象的过程交给Spring容器

2.IOC:面向切面编程,不改源代码进行功能增强

bean.xml文件

<bean id = "昵称" class = "类的全类名" ></bean>

测试 

1.加载spring配置文件
ApplicationContext  context  = new ClassPathXmlApplicationContext("bean.xml");//src下的可以直接这样扫描
2.得到配置的对象
  类名 昵称= context.getBean("bean中ID",类名.class);

3.调用bean中对象类中的方法
  昵称.method();

IOC容器:

(1)IOC底层原理

(2)IOC接口(BeanFactory)

(3)IOC操作Bean管理(注解与xml)

 控制反转-->对象的创建与对象调度都交给spring管理

(1):...

------> 原始模式(耦合度高)

Spring5复习IOC与AOP

 

 ------>工厂模式

Spring5复习IOC与AOP

 

 ------>IOC过程

IOC(接口)

IOC思想基于IOC容器,底层是对象工厂

 Spring提供IOC容器实现的两种方式(两个接口)加载配置文件,获取配置创建对象

(1)BeanFactory:spring内置接口,不提供给开发人员使用。

加载配置文件时 不创建对象,获取(使用)对象的时候才会创建对象----getBean("");

(2)ApplicationContext:上面的子接口,功能更强,开发人员使用

加载即创建。

(3)ApplicationContext接口的实现类

Spring5复习IOC与AOP

 IOC操作Bean管理

(1)xml

(2)注解

创建对象时默认执行无参构造方法 

xml方式注入属性:

(1)DI:依赖注入(ioc的一种具体实现)

    1. set方法注入:

//在类中生成set方法

<bean id = "" class =""> <!-- name:类中属性名称 value:向属性中注入的值 --> <property name = "" value =""></property> </bean>

    2. 有参注入:

//在类中生成有参构造方法

<bean id ="" class = ""> <constructor-arg name = "" value =""> </contructor-arg> </bean>

    p 名称空间注入

(1)用于简化xml配置

   

  //添加p名称空间
  xmlns:p="http://www.springframework.org/schema/p"
  //set注入属性
  <bean id = "" class = "" p:属性名 = "属性值" >
 
 </bean>

xml注入其他类型:

null:
  <property name ="">
    <null/>
  </property>


特殊符号:
    <property name ="" >
    <value>
     < <![CDATA[****]]>>

     </value>
     </property>

注入属性-外部bean

(1)创建两个类  service 和 mapper

(2) service 调用 mapper 

 Spring5复习IOC与AOP

 

 <!-- ref 就是将外部的bean注入进来-->

Spring5复习IOC与AOP

 

 注入属性-内部bean和级联赋值

(1)一对多

(2)实体类中表示一对多关系

Spring5复习IOC与AOP

 

 

 

<!-- emp 对象-->
<bean id = "emp" class = "">
<!-- emp的属性和dept对象属性--> <property name = "" value = ""> </property> <property name = "dept" > <bean id = "dept" class = "">
<property name = "" value = ""></property>
</bean> <property>
</bean>

---------------------------------------------------内部bean

注入属性-级联赋值1

<!-- emp 对象-->
<bean id  = "emp" class = "">
<!-- emp的属性和dept对象属性-->
    <property name = "" value = ""> </property>
    <property name = "dept" ref = "dept"></property>
<!--外部bean 级联赋值-->
</bean>
        <bean id = "dept" class = "">
              <property name  = "" value = ""><property>
 </bean>

注入属性-级联赋值2(猜测比外部级联优先级高)

<!-- emp 对象 生成一下getDept方法-->
<bean id  = "emp" class = "">
<!-- emp的属性和dept对象属性-->
    <property name = "" value = ""> </property>
    <property name = "dept" ref = "dept"></property>
     <property name = "dept.dname" value= ""></property>
<!--外部bean 级联赋值-->
</bean>
        <bean id = "dept" class = "">
              <property name  = "" value = ""><property>
 </bean>

xml注入集合属性:

Spring5复习IOC与AOP

 

 

<!-- 数组-->
<bean ...>
    <property name = "course">
     <array>
        <value>...</value>
                 ......
        </array>
    </property>     

<!-- map -->

    <property name = "maps">
     <map>
        <entry key = "" value = ""> </entry>
                 ......
        </map>
    </property>     

<!-- list-->

    <property name = "list">
     <list>
        <value>...</value>
                 ......
        </list>
    </property>     

<!-- set-->

    <property name = "list">
     <set>
        <value>...</value>
                 ......
        </set>
    </property>     

 注入集合对象2

 Spring5复习IOC与AOP

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


<!--创建多个course对象-->
<bean 1>
<property/>
....
<bean 2>
<property/>
....

把集合注入部分提取出来:

引入名称空间util

Spring5复习IOC与AOP

 

 

<util:list id = "bookList">
    <value></value>
    <value></value>
</util:list>



<bean id  = "book " class = "">
   <property name = '"'  ref = "bookList"></>
</>

 IOC操作bean管理(FactoryBean)

1. 普通bean

2.FactoryBean (定义bean类型与返回类型可以不同)

第一步 :创建类 ,作为工厂bean ,实现FactoryBean 。

第二步 :实现接口里面的方法,在实现方法中定义返回的bean类型

public class MyBean implements FactoryBean<Course>{
       //定义返回Bean
       public Course getObject () throws Exception{
                    new Course();-->course
                            course.setCname("....");
                                  return course;
      }
          public Class<?> getObjectType() {
               return null;

           }
         public boolean isSingleton () {
                     return false;
         
    }
           

}
--------------------------------------------------------------------
<bean id = "myBean" class = ""></bean>
.....

context.getBean("myBean", Course.class); --->course

bean的作用域:

通过scope属性的值来设置:

scope = "singleton"(默认)  加载配置文件时就会创建单实例对象

prototype:多实例  调用getBean方法时创建多实例对象

request:一次请求

session:一次会话

bean的生命周期:

(1)无参构造创建bean实例

(2)为bean的属性设置值,对其他bean的引入(调用set方法)

(3)把bean实例传递给bean后置处理器postProcessBeforeInitialization方法

(3)调用bean的初始化的方法

(4)把bean实例传递给bean后置处理器postProcessAfterInitialization方法

(4)使用bean

(5)容器关闭时,调用bean的销毁方法。

//在类中创建初始化方法 init () 和 销毁方法 destroy()
<bean id  =  "" class  = "" init-method = "init " destroy-method = "destroy"> 
<property></>
</bean>
..........
contex.close();
ApplicationContext接口中没有close方法
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext ();

添加后置处理器:

(1)创建类 MyBeanPost,实现BeanPostProcessor接口

(2)实现其中两个方法

<!-- 配置后置处理器  为配置文件中所有bean实例创建后置处理器-->
<bean id  = "myBeanPost" class = "....MyBeanPost">

xml自动装配:

根据指定装配规则(属性名称 属性类型),Spring指定将匹配的属性值进行注入

autowire = "byName";byType;

byName 注入值bean得id值与类的属性名称一致

外部属性文件:

Spring5复习IOC与AOP

 

1.创建外部属性文件

Spring5复习IOC与AOP

2. 在配置文件中添加context命名空间

<!-- 引入外部文件-->
<context:property-placeholder location ="classpath:jdbc.properties" >
<!-- 配置连接池-->
<bean id="dataSource"class="com.alibaba.druid.pool.DruidDataSource">
  <property name = "driverClassName" value"${prop.driverClass}"></property>
.....
</bean>

 

IOC注解

Spring针对bean管理中创建对象提供的注解:

(1)@Component

(2)@Service

(3)@Controller

(4)@Repository

基于注解实现对象创建

第一步  引入依赖

第二步  开启组件扫描<context>

多个包之间 逗号隔开(扫描上层目录也行)

<context:component-scan base-package = " "></context:component-scan>

第三步 创建类 在类上添加注解

//自定义配置filter
<context : component-scan base-package = "" use-default-filters = "false">
<context : include-filter type = "annotation" expression = "org.springframework.stereotype.Controller"/>
</>
exclude-filter type 不扫描哪些内容

注解实现属性注入:

(1)@AutoWired :根据属性类型注入

(2)@Qualifier:根据属性名称注入

根据类型注入,一个借口可能有多个实现类,可以在AutoWired 下添加Qualifier(value ="userDaoImpl1")

(3)@Resource:都行

如果要根据名称注入 Resource(name = "")

(4)@Value:注入普通类型属性

    为定义的属性赋值

Spring5复习IOC与AOP

service中定义dao类型属性,是由于spring的设计思想是利用java的多态特性 减少耦合

完全注解开发:

配置类:SpringConfig

@Configuration

@Component(basePackages ={""})

 SpringConfig

加载配置类

new AnnotationConfigApplicationContext(SpringConfig.class);-->ApplicationContext

 

AOP(底层动态代理)

不改源代码,增加新功能

动态代理:

(1)有接口:创建接口实现类代理对象,增强类方法

(2)没有接口:创建类的子类代理对象

1.JDK动态代理,使用Proxy类里面的方法创建代理对象

调用nexProxyInstance方法

Spring5复习IOC与AOP

 

 参数一:类加载器

 参数二:增强方法所在的类,这个类实现的接口,支持多个接口

 参数三:实现这个接口InvocationHandler,创建代理对象,写增强部分的代码

Spring5复习IOC与AOP

 

 

public class JDKProxy{
   psvm{
<!-- 创建接口实现类代理对象-->
            Class [] interfaces = {UserDao.class};
UserDaoImpl userDao = new UserDaoImpl();
      Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new InvocationHandler(){
public Object invoke (Object proxy,Method method,Object[] args) throws Throwable{
     return null;
}
}
);
-------------------------------------------------------------------------
UserDao dao 
=Proxy.newProxyInstance(JDKProxy.class.getClassLoader(),interfaces,new UserDapProxy(userDao) );




    }
}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler{
//把创建的是谁的代理对象,就把谁传递过来
//有参构造传递
  private Object obj;
 public UserDaoProxy(Oject obj){
    this.obj = obj;   
}



  public Object invoke (Object proxy,Method method,Object[] args) throws Throwable{
  
   Onject  res  =  method.invoke(obj,args);
     return res;
}
}

Aop(术语)

1.连接点:可以被增强的方法

2.切入点:实际被增强的方法

3.通知(增强):增加的部分逻辑

    前置通知  后置通知  环绕通知  异常通知  最终通知

4.切面

  把通知应用到切入点的过程

基于AspectJ实现AOP操作

独立的AOP框架

切入点表达式

作用:知道哪个类里面的哪个方法进行增强

execution([权限修饰符] [返回类型][全类名][方法名称]([参数列表]))

AspectJ注解

(1)xml中添加context,aop命名空间,开启注解扫描

(2)使用注解创建User和UserProxy对象

(3)增强类上加注解@Aspect 生成代理对象

(4)开启Aspect生成代理对象

<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

@Component
@Aspect
public class UserProxy{
//前置通知 @Before(value = "execution(*org.xxx.User.add(..))") public void before(){ System.out.println("...."); } }
@After(value = "")最终通知
@AfterReturning(value = "")后置通知 (返回通知)有异常不执行
@Around(value = "")环绕通知 参数为 ProceedingJoinPoint proceedingJoinPoint
sout 前
proceedingJoinPoint.proceed();
sout 后
@AfterThrowing(value = "")异常通知

Spring5复习IOC与AOP

 

 

 抽取相同的切入点

@Pointcut(value = "execution(*org.xxx.User.add(..))")

public void pointdemo(){

}

@Before (value = "pointdemo()")

多个增强类对一个方法进行增强:优先级

增强类上加一个注解@Order(数值类型放入值)值小优先级高

配置文件做AspectJ

<!-- 配置AOP增强-->
 <aop:config>
    <!-- 切入点-->
      <aop:pointcut id = "p" expression = "execution(*org.xxx.Book.Buy(..))"/>
   <!-- 配置切面-->
<aop :aspect ref = "bookProxy">
  <!--增强作用在具体的方法上-->
  <aop:before method = "before"  pointcut-ref = "p" >
 </aop:aspect>
</aop:config>

<bean id ="book" class = ""></>
<bean id  ="bookProxy" class = "">

@EnableAspectJAutoProxy(proxyTargetClass = true)

 

上一篇:Spring5--@Indexed注解加快启动速度


下一篇:Spring5.x 学习笔记(二)IOC 容器