Spring

Spring

IOC / AOP

Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。如何理解好Ioc呢?理解好Ioc的关键是要明确“谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了”,那我们来深入分析一下:

谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象;而IoC是有专门一个容器来创建这些对象,即由Ioc容器来控制对 象的创建;谁控制谁?当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。

为何是反转,哪些方面反转了:有反转就有正转,传统应用程序是由我们自己在对象中主动控制去直接获取依赖对象,也就是正转;而反转则是由容器来帮忙创建及注入依赖对象;为何是反转?因为由容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以是反转;哪些方面反转了?依赖对象的获取被反转了。

HelloSpring

package com.yrz.pojo;

public class Hello {
    private String str;

    public String getStr() {
        return str;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public String toString() {
        return "Hello{" +
                "str='" + str + '\'' +
                '}';
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="hello" class="com.yrz.pojo.Hello">
        <property name="str" value="YRZ"/>
    </bean>
</beans>
import com.yrz.pojo.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        //获取spring的上下文对象
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        Hello hello = (Hello) context.getBean("hello");
        System.out.println(hello.toString());
    }
    }

IOC创建对象的方式

package com.yrz.pojo;

public class User {
    private String name;

    public User(String name){
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public void show() {
        System.out.println("name="+name);
    }

}

构造器注入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="user" class="com.yrz.pojo.User">
        <!--第一种:下标赋值-->
        <constructor-arg index="0" value="yrz"/>
    </bean>
    <bean id="user" class="com.yrz.pojo.User">
        <!--第二种:类型赋值(不建议使用)-->
        <constructor-arg type="java.lang.String" value="yrz"/>
    </bean>
    <bean id="user" class="com.yrz.pojo.User">
        <!--第三种:参数名赋值-->
        <constructor-arg name="name" value="yrz"/>
    </bean>
</beans>
import com.yrz.pojo.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
        User user = (User) context.getBean("user");
        user.show();
    }
}

依赖注入之–Set注入(重点)

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd">

    <bean id="address" class="com.yrz.pojo.Address">
        <property name="address" value="上海"></property>
    </bean>
    <bean id="student" class="com.yrz.pojo.Student">
        <!--第一种:普通注入-->
        <property name="name" value="yrz"></property>
        <!--第二种:bean注入,ref-->
        <property name="address" ref="address"></property>
        <!--数组-->
        <property name="books">
            <array>
                <value>红楼梦</value>
                <value>西游记</value>
                <value>三国演义</value>
                <value>水浒传</value>
            </array>
        </property>
        <!--List-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>打游戏</value>
                <value>看电影</value>
            </list>
        </property>
        <!--Map-->
        <property name="card">
            <map>
                <entry key="身份证" value="6531"></entry>
                <entry key="学生证" value="1998"></entry>
            </map>
        </property>
        <!--Set-->
        <property name="game">
            <set>
              <value>LOL</value>
              <value>COC</value>
            </set>
        </property>
        <!--null-->
        <property name="wife">
            <null></null>
        </property>
        <!--properties-->
        <property name="info">
            <props>
                <prop key="学号">132456</prop>
                <prop key="性别"></prop>
                <prop key="名字">Y</prop>
            </props>
        </property>
</bean>
</beans>

注解自动装配

package com.yrz.pojo;


import org.springframework.beans.factory.annotation.Autowired;

public class People {
    private String name;
    @Autowired
    private Cat cat;
    @Autowired
    private Dog dog;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Cat getCat() {
        return cat;
    }

    public void setCat(Cat cat) {
        this.cat = cat;
    }

    public Dog getDog() {
        return dog;
    }

    public void setDog(Dog dog) {
        this.dog = dog;
    }

    @Override
    public String toString() {
        return "People{" +
                "name='" + name + '\'' +
                ", cat=" + cat +
                ", dog=" + dog +
                '}';
    }
}
<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd

    <context:annotation-config/>
    <bean id="cat" class="com.yrz.pojo.Cat"></bean>
    <bean id="dog" class="com.yrz.pojo.Dog"></bean>
    <bean id="people" class="com.yrz.pojo.People"></bean>

</beans>
import com.yrz.pojo.People;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {

        @Test
        public void test1(){
            ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
            People people = context.getBean("people", People.class);
            people.getCat().shout();
            people.getDog().shout();
        }
    }

在xml中开启注解的支持

<!--指定要扫描的包-->
<context:component-scan base-package="com.yrz.pojo"/>
<context:annotation-config/>

@Autowired:自动装配先通过类型,再通过名字

@Resource:自动装配先通过名字,再通过类型

@Qualifier:使用@Qualifier(value="")去配置@Autowired的使用

@Component(“user”):// 相当于配置文件中

–dao【@Repository】

–service【@Service】

–controller【@Controller】【@RestController】-- 不走视图层,返回字符串

@Scope:作用域

@Configuration:代表这是一个配置类,和beans.xml一样

@Bean:作用于方法上,相当于bean标签,id是方法名,class是返回值

@ComponentScan:扫描Component

@Aspect:标志这个类是一个切面

package com.yrz.pojo;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

//相当于配置文件中 <bean id="user" class="当前注解的类"/>
@Component
//作用域
@Scope("prototype")
public class User {
    public String name;

    //相当于 <property name = "name" value = "YRZ"/>
    @Value("YRZ")

    public void setName(String name) {
        this.name = name;
    }
}

静态代理模式

UserService

package com.yrz.demo02;

public interface UserService {
    public void add();
    public void delete();
    public void update();
    public void query();
}

UserServiceImpl

package com.yrz.demo02;

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("add");
    }
    public void delete() {
        System.out.println("delete");
    }
    public void update() {
        System.out.println("update");
    }
    public void query() {
        System.out.println("query");
    }
}

UserServiceProxy

package com.yrz.demo02;

public class UserServiceProxy implements UserService{
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    public void add() {
        log("add");
        userService.add();
    }
    public void delete() {
        log("delete");
        userService.delete();
    }
    public void update() {
        log("update");
        userService.update();
    }
    public void query() {
        log("query");
        userService.query();
    }
    public void log(String msg){
        System.out.println("[Debug]使用了"+msg+"方法");
    }
}

Client

package com.yrz.demo02;

public class Client {
    public Client() {
    }

    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        UserServiceProxy proxy = new UserServiceProxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}

动态代理模式

  • 基于接口–JDK动态代理

了解两个类:

  • Proxy–代理
  • InvocationHandler–调用处理程序

ProxyInvocationHandler

package com.yrz.demo04;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class ProxyInvocationHandler implements InvocationHandler {
    //被代理的接口
    private Object target;
    public void setTarget(Object target) {
        this.target = target;
    }
    
    //生成得到代理类
    public Object getProxy(){
        return Proxy.newProxyInstance(this.getClass().getClassLoader()
                ,target.getClass().getInterfaces(),this);
    }

    //处理代理实例,并返回结果
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object result = method.invoke(target, args);
        return result;
    }
    public void log(String msg){
        System.out.println("使用了"+msg+"方法");
    }
}

Client

package com.yrz.demo04;

import com.yrz.demo02.UserService;
import com.yrz.demo02.UserServiceImpl;

public class Client {
    public static void main(String[] args) {
        //真实角色
        UserServiceImpl userService = new UserServiceImpl();
        //代理角色,不存在
        ProxyInvocationHandler pih = new ProxyInvocationHandler();

        pih.setTarget(userService);//设置要代理的对象
        //动态生成代理类
        UserService proxy = (UserService) pih.getProxy();
        proxy.delete();
    }
}

AOP实现方式一

使用原生Spring API接口(主要是Spring API接口实现)

package com.yrz.service;

public class UserServiceImpl implements UserService{
    public void add() {
        System.out.println("增");
    }

    public void delete() {
        System.out.println("删");
    }

    public void update() {
        System.out.println("改");
    }

    public void select() {
        System.out.println("查");
    }
}
package com.yrz.service;
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;

public class Log implements MethodBeforeAdvice {
    //method:要执行的目标对象方法
    //args:参数
    //target:目标
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println(target.getClass().getName()+"的"+method.getName()+"方法被执行了");
    }
}
package com.yrz.service;
import org.springframework.aop.AfterReturningAdvice;
import java.lang.reflect.Method;

public class AfterLog implements AfterReturningAdvice {
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
        System.out.println("执行了"+method.getName()+"方法,返回值结果为:"+returnValue);
    }
}
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    
    <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean>
    <bean id="log" class="com.yrz.service.Log"></bean>
    <bean id="afterLog" class="com.yrz.service.AfterLog"></bean>

<!--方式一:使用原生Spring API接口-->
<!--配置aop-->
    <aop:config>
    <!--切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.yrz.service.UserServiceImpl.*(..))"/>
    <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"></aop:advisor>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"></aop:advisor>
    </aop:config>
</beans>
import com.yrz.service.UserService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

AOP实现方式二

使用自定义类来实现AOP(主要是切面定义)

package com.yrz.diy;

public class DiyPointCut {
    public void before(){
        System.out.println("========方法执行前========");
    }
    public void after(){
        System.out.println("========方法执行后========");
    }
}
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean>
    <bean id="log" class="com.yrz.service.Log"></bean>
    <bean id="afterLog" class="com.yrz.service.AfterLog"></bean>

<!--方式二:自定义类-->
    <bean id="diy" class="com.yrz.diy.DiyPointCut"></bean>
    <aop:config>
        <!--自定义切面,ref要引用的类-->
        <aop:aspect ref="diy">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.yrz.service.UserServiceImpl.*(..))"/>
            <aop:before method="before" pointcut-ref="point"></aop:before>
            <aop:after method="after" pointcut-ref="point"></aop:after>
        </aop:aspect>
    </aop:config>
</beans>

AOP实现方式三

注解实现AOP

package com.yrz.diy;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;

@Aspect //标注这个类是一个切面
public class AnnotationPointCut {
    @Before("execution(* com.yrz.service.UserServiceImpl.*(..))")
    public void before(){
        System.out.println("执行前");
    }
    @After("execution(* com.yrz.service.UserServiceImpl.*(..))")
    public void after(){
        System.out.println("执行后");
    }
}
<?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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="userService" class="com.yrz.service.UserServiceImpl"></bean>
    <bean id="log" class="com.yrz.service.Log"></bean>
    <bean id="afterLog" class="com.yrz.service.AfterLog"></bean>

    <!--方式三-->
    <bean id="annotationPointCut" class="com.yrz.diy.AnnotationPointCut"></bean>
    <!--开启注解支持-->
    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Boom'

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值