百度站长怎么验证网站,wordpress 二级链接,怎么注册域名,安阳县吕村七中录取分数线使用注解开发
在Spring4之后#xff0c;要使用注解开发#xff0c;必须要保证AOP的包导入了 项目搭建#xff1a; 在配置文件中导入约束#xff0c;增加注解支持 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.spri…使用注解开发
在Spring4之后要使用注解开发必须要保证AOP的包导入了 项目搭建 在配置文件中导入约束增加注解支持 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsdcontext:annotation-config//beans?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd!--指定要扫描的包这个包下的注解就会生效--context:component-scan base-packagexyz.luck1y.pojo/!--注解驱动的包可以识别spring之外的注解如前面说的Resource等等--context:annotation-config//beansbean 实体类 Component 注解 package xyz.luck1y.pojo;import org.springframework.stereotype.Component;// 等价于xml中的 bean iduser classcom.luck1y.pojo.User/
// Component 意为组件说明这个类已经被Spring管理啦在xml中配置了组件扫描
Component
public class User {public String name 刘子;
}xml配置 ?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:contexthttp://www.springframework.org/schema/contextxsi:schemaLocationhttp://www.springframework.org/schema/beanshttps://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttps://www.springframework.org/schema/context/spring-context.xsd!--指定要扫描的包这个包下的注解就会生效--context:component-scan base-packagexyz.luck1y.pojo/!--注解驱动的包可以识别spring之外的注解如前面说的Resource等等--context:annotation-config//beans测试 import org.springframework.context.support.ClassPathXmlApplicationContext;
import xyz.luck1y.pojo.User;public class MyTest {public static void main(String[] args) {ClassPathXmlApplicationContext context new ClassPathXmlApplicationContext(applicationContext.xml);User user context.getBean(user, User.class);System.out.println(user.name);}
}属性如何注入
package xyz.luck1y.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;// 等价于xml中的 bean iduser classcom.luck1y.pojo.User/
// Component 意为组件说明这个类已经被Spring管理啦在xml中配置了组件扫描
Component
public class User {// 相当于property namename value刘子/// 如果是很复杂的配置还是建议使用xmlValue(刘子)public String name;// 也可以写在set方法上Value(刘子)public void setName(String name) {this.name name;}
}衍生的注解
Component有几个衍生的注解我们在web开发中会按照MVC三层架构分层 dao层 Repository 等价于pojo层的Component package xyz.luck1y.dao;import org.springframework.stereotype.Repository;Repository
public class UserDao {
}service层Service 同样等价于pojo层的Component package xyz.luck1y.service;import org.springframework.stereotype.Service;Service
public class UserService {
}controller层也就是以前的servlet层Controller还是等价于pojo层的Component package xyz.luck1y.controller;import org.springframework.stereotype.Controller;Controller
public class UserController {
}这样写的话前面的xml配置文件中componment组件扫描范围要扩大
context:component-scan base-packagexyz.luck1y/这四个注解功能是一样的都是代表将某个类注册到Spring容器中装配bean
作用域
// 单例
Scope(singleton)
// 原型
Scope(prototype)小结
xml和注解
xml更加万能适用于任何场合维护简单方便注解不是自己的类用不了无法引用别的类维护相对复杂
最佳实践
xml用来管理bean注解用来完成属性的注入我们在使用的过程中需要注意必须要让注解生效即在配置文件中开启注解支持
使用Java的方式配置Spring
完全不使用Spring的xml配置全交给Java来做
JavaConfig是Spring的一个子项目在Spring4之后它成为了一个核心功能~
使用Java配置类来配置Spring
主配置类
package xyz.luck1y.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import xyz.luck1y.pojo.User;// 相当于扫描包
ComponentScan(xyz.luck1y.pojo)
// 这个也会被Spring容器托管注册到容器中因为它本来就是一个Component它代表这是一个配置类就是beans.xml
Configuration
// 相当于xml中引入其他xml
Import(MyConfig2.class)
public class MyConfig {// 注册一个 bean 就相当于我们之前写的bean标签// id 标签 就是这个方法的名字// class 标签 就是这个方法的返回值类型Beanpublic User getUser(){return new User();}
}配置类2
package xyz.luck1y.config;import org.springframework.context.annotation.Configuration;Configuration
public class MyConfig2 {
}实体类
package xyz.luck1y.pojo;import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;Component
public class User {Value(刘子)public String name;public String getName() {return name;}public void setName(String name) {this.name name;}Overridepublic String toString() {return User{ name name \ };}
}测试
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import xyz.luck1y.config.MyConfig;
import xyz.luck1y.pojo.User;public class MyTest {public static void main(String[] args) {// 如果完全使用了配置类的方式去做我们就只能通过AnnotationConfigApplicationContext 上下文来获取容器通过配置类.class获取AnnotationConfigApplicationContext context new AnnotationConfigApplicationContext(MyConfig.class);User user context.getBean(user, User.class);System.out.println(user.getName());}
}其实SpringBoot底层代码都是用以上注解方式写的为什么说SpringBoot比Spring更强大呢就是因为它在底层都固定写好了这些注解拿过来直接用就好了~
代理模式
多线程那块提到过代理模式这里再来学习一下代理模式
代理模式是SpringAOP的底层SpringAOP和SpringMVC是面试重点
代理模式的分类
静态代理动态代理 静态代理
角色分析
抽象角色一般会使用接口或抽象类来解决真实角色被代理的角色代理角色代理真实角色代理真实角色后会做一系列的附属操作客户访问代理对象的人
代理模式的好处
可以使真实角色的操作更加纯粹不用去关注其他的公共业务公共业务交给代理角色实现了业务的分工不需要给每一个房东都加相同的功能这些相同的功能都提取到代理角色业务发生扩展的时候方便集中管理
缺点
一个真实角色就会产生一个代理角色真实角色变多时代码量会翻倍开发效率会变低为了解决这个问题便有了动态代理
测试 租房接口 package xyz.luck1y;// 租房的接口
public interface Rent {public void rent();
}房东真实角色 package xyz.luck1y;public class Host implements Rent {Overridepublic void rent() {System.out.println(房东要出租房子);}
}中介代理角色 package xyz.luck1y;public class Proxy implements Rent {private Host host;public Proxy(){}public Proxy(Host host) {this.host host;}Overridepublic void rent() {seeHouse();host.rent();heTong();fee();}// 看房public void seeHouse(){System.out.println(中介带你看房);}// 签合同public void heTong(){System.out.println(签署租赁合同);}// 收中介费public void fee(){System.out.println(收中介费);}
}客户我们 package xyz.luck1y;public class Client {public static void main(String[] args) {// 房东要租房子Host host new Host();// 代理中介来帮房东租房子但是中介一般有一些其他操作Proxy proxy new Proxy(host);// 你不用面对房东直接找中介租房就行proxy.rent();}
}加深理解 接口 package xyz.luck1y.Demo02;public interface UserService {public void add();public void delete();public void update();public void query();
}真实对象 package xyz.luck1y.Demo02;
// 真实对象
public class UserServiceImpl implements UserService {Overridepublic void add() {System.out.println(增加了一个用户);}Overridepublic void delete() {System.out.println(删除了一个用户);}Overridepublic void update() {System.out.println(修改了一个用户);}Overridepublic void query() {System.out.println(查询了一个用户);}
}代理对象 package xyz.luck1y.Demo02;public class UserServiceProxy implements UserService {private UserServiceImpl userService;public void setUserService(UserServiceImpl userService) {this.userService userService;}Overridepublic void add() {log(add);userService.add();}Overridepublic void delete() {log(delete);userService.delete();}Overridepublic void update() {log(update);userService.update();}Overridepublic void query() {log(query);userService.query();}// 日志public void log(String msg){System.out.println([Debug] 使用了 msg 方法);}
}客户端 package xyz.luck1y.Demo02;public class Client {public static void main(String[] args) {UserServiceImpl userService new UserServiceImpl();UserServiceProxy userServiceProxy new UserServiceProxy();userServiceProxy.setUserService(userService);userServiceProxy.add();}
}为什么不直接在原来的真实对象类加新的内容
改动原有的业务代码在工作中是大忌新增一个类本来跑的好好的崩了怎么办~
加一个代理类可以在原有业务代码不变的基础上进行安全地附加操作
关于AOP 动态代理 动态代理和静态代理的角色一样 动态代理的代理类是动态生成的不是我们直接写好的 动态代理也分为两大类基于接口的动态代理、基于类的动态代理 基于接口的动态代理【我们在这里使用这种方式】JDK的动态代理 基于类的动态代理cglib Java字节码实现javasist
需要了解两个类Proxy代理InvocationHandler调用处理程序 InvocationHandler 一个接口java.lang.reflect反射包下 InvocationHandler是由代理实例的调用处理程序实现的接口每个代理实例都有一个关联的调用处理程序。当在代理实例上调用方法时方法调用将被编码并分派到其调用处理程序的invoke方法。 这个接口只有一个方法Object invoke(Object proxy , 方法 method , Object[] args) throws Throwable Proxy: 一个类java.lang.reflect反射包下 Proxy提供了创建动态代理类和实例的静态方法它也是由这些方法创建的所有动态代理类的超类。也就说说可以通过类来调用方法。 代码实现
自动生成代理类
package xyz.luck1y.Demo03;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;// 用这个类自动生成代理类
public class ProxyInvocationHandler implements InvocationHandler {// 被代理的接口private Rent rent;public void setRent(Rent rent){this.rent rent;}// 生成得到代理类public Object getProxy(){return Proxy.newProxyInstance(this.getClass().getClassLoader(), rent.getClass().getInterfaces(), this);}// 处理代理实例并返回结果Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 动态代理的本质就是通过反射机制实现log(method.getName());seeHose();Object result method.invoke(rent, args);getFee();return null;}public void seeHose(){System.out.println(中介带着看房子);}public void getFee(){System.out.println(收取中介费用);}public void log(String msg) {System.out.println([Log] 执行了 msg 方法);}
}客户端
package xyz.luck1y.Demo03;import xyz.luck1y.Demo02.UserServiceImpl;public class Client {public static void main(String[] args) {// 真实角色Host host new Host();// 代理角色不存在ProxyInvocationHandler pih new ProxyInvocationHandler();// 通过调用程序处理角色来处理我们要调用的接口对象pih.setRent(host);Rent proxy (Rent) pih.getProxy();proxy.rent();}
}房东和租房接口
package xyz.luck1y.Demo03;public class Host implements Rent {Overridepublic void rent() {System.out.println(房东要出租房子);}
}package xyz.luck1y.Demo03;// 租房的接口
public interface Rent {public void rent();
}测试结果 进一步观察
package xyz.luck1y.Demo04;import xyz.luck1y.Demo03.Rent;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);}// 处理代理实例并返回结果Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 动态代理的本质就是通过反射机制实现log(method.getName());seeHose();Object result method.invoke(target, args);getFee();return null;}public void seeHose(){System.out.println(中介带着看房子);}public void getFee(){System.out.println(收取中介费用);}public void log(String msg) {System.out.println([Log] 执行了 msg 方法);}
}package xyz.luck1y.Demo04;import xyz.luck1y.Demo02.UserService;
import xyz.luck1y.Demo02.UserServiceImpl;
import xyz.luck1y.Demo03.Host;
import xyz.luck1y.Demo03.Rent;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.add();}
}动态代理的优点
可以使真实角色的操作更加纯粹不用去关注真实角色的公共业务公共业务交给代理角色实现了业务的分工例子中不需要给每一个房东都加相同的功能这些相同的功能都提取到代理角色业务发生扩展的时候方便集中管理一个动态代理类代理的是一个接口一般就是对应的一类业务一个动态代理类可以代理多个类只要是实现类同一个接口即可。
AOP
什么是AOP
AOP (Aspect Oriented Programming)意为面向切面编程通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是0OP的延续,是软件开发中一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性同时提高了开发的效率。 AOP在Spring中的作用
提供声明式事务允许用户自定义切面
横切关注点跨越应用程序多个模块的方法或功能即与我们业务逻辑无关的但是我们需要关注的部分就是横切关注点。如日志、安全、缓存、事务等等切面Aspect横切关注点 被模块化的特殊对象即它是一个类通知Advice切面必须要完成的工作即它是类中的一个方法目标Target被通知对象代理Proxy向目标对象应用通知之后创建的对象切入点PointCut切面通知执行的“地点”的定义连接点JoinPoint与切入点匹配的执行点 在SpringAOP中通过Advice定义横切逻辑Spring支持五种类型的Advice 即AOP可以在不改变原有代码的情况下为业务增加新的功能。
使用Spring实现AOP
AOP织入包需要导入一个依赖包
dependencygroupIdorg.aspectj/groupIdartifactIdaspectjweaver/artifactIdversion1.9.6/version
/dependency方式一使用Spring的API接口
接口
package xyz.luck1y.service;public interface UserService {public void add();public void delete();public void update();public void select();
}实现类
package xyz.luck1y.service;public class UserServiceImpl implements UserService {Overridepublic void add() {System.out.println(增加了一个用户);}Overridepublic void delete() {System.out.println(删除了一个用户);}Overridepublic void update() {System.out.println(修改了一个用户);}Overridepublic void select() {System.out.println(查询了一个用户);}
}AOP增加日志功能
package xyz.luck1y.log;import org.springframework.aop.MethodBeforeAdvice;import java.lang.reflect.Method;public class Log implements MethodBeforeAdvice {// method要执行的目标对象的方法// args参数// target目标对象Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println(target.getClass().getName() 的 method.getName() 被执行了);}
}package xyz.luck1y.log;import org.springframework.aop.AfterReturningAdvice;import java.lang.reflect.Method;public class AfterLog implements AfterReturningAdvice {// returnValue返回值Overridepublic void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {System.out.println(执行了 method.getName() 方法返回结果为 returnValue);}
}xml配置文件
注意在前面写好aop约束
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd!--注册bean--bean iduserService classxyz.luck1y.service.UserServiceImpl/bean idlog classxyz.luck1y.log.Log/bean idafterLog classxyz.luck1y.log.AfterLog/!--方式一使用原生的Spring API接口--!--配置aop:需要导入aop的约束--aop:config!--切入点expression表达式execution(要执行的位置 修饰词 返回值 类名 方法名 参数) .. 代表有任意的参数--aop:pointcut idpointcut expressionexecution(* xyz.luck1y.service.UserServiceImpl.*(..))/!--执行环绕增加--aop:advisor advice-reflog pointcut-refpointcut/aop:advisor advice-refafterLog pointcut-refpointcut//aop:config
/beans测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xyz.luck1y.service.UserService;public class MyTest {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(applicationContent.xml);// 动态代理代理的是接口此处为 UserService 接口UserService userService context.getBean(userService, UserService.class);userService.add();}
}结果 方式二自定义类实现实现AOP
自定义切面插入类
package xyz.luck1y.diy;public class DiyPointCut {public void before(){System.out.println(方法执行前);}public void after(){System.out.println(方法执后);}
}配置文件
?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd!--注册bean--bean iduserService classxyz.luck1y.service.UserServiceImpl/bean idlog classxyz.luck1y.log.Log/bean idafterLog classxyz.luck1y.log.AfterLog/!--方式二自定义类--!--比第一类简单但是功能没有第一种强大--bean iddiy classxyz.luck1y.diy.DiyPointCut/aop:config!--自定义切面ref要引用的类--aop:aspect refdiy!--切入点--aop:pointcut idpoint expressionexecution(* xyz.luck1y.service.UserServiceImpl.*(..))/!--通知--aop:before methodbefore pointcut-refpoint/aop:before methodafter pointcut-refpoint//aop:aspect/aop:config
/beans测试
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import xyz.luck1y.service.UserService;public class MyTest {public static void main(String[] args) {ApplicationContext context new ClassPathXmlApplicationContext(applicationContent.xml);// 动态代理代理的是接口此处为 UserService 接口UserService userService context.getBean(userService, UserService.class);userService.add();}
}结果 方式三使用注解实现AOP
package xyz.luck1y.diy;
// 方式三使用注解方式实现AOPimport org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;// 标注这个类是一个切面
Aspect
public class AnnotationPointCut {Before(execution(* xyz.luck1y.service.UserServiceImpl.*(..)))public void before(){System.out.println(方法执行前);}After(execution(* xyz.luck1y.service.UserServiceImpl.*(..)))public void after(){System.out.println(方法执行后);}// 在环绕增强中我们可以给定一个参数代表我们要获取处理切入的点Around(execution(* xyz.luck1y.service.UserServiceImpl.*(..)))public void around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println(环绕前);// 获得签名Signature signature joinPoint.getSignature();System.out.println(signature: signature);// 执行方法Object proceed joinPoint.proceed();System.out.println(环绕后);System.out.println(proceed);}
}?xml version1.0 encodingUTF-8?
beans xmlnshttp://www.springframework.org/schema/beansxmlns:xsihttp://www.w3.org/2001/XMLSchema-instancexmlns:aophttp://www.springframework.org/schema/aopxsi:schemaLocationhttp://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd!--注册bean--bean iduserService classxyz.luck1y.service.UserServiceImpl/bean idlog classxyz.luck1y.log.Log/bean idafterLog classxyz.luck1y.log.AfterLog/!--方式三使用注解--bean idannotationPointCut classxyz.luck1y.diy.AnnotationPointCut/!--开启注解支持 JDK(默认实现) CGLib--!--proxy-target-class 设置为 false 为 JDK 实现true 是 CGLib 实现--aop:aspectj-autoproxy proxy-target-classfalse/
/beans测试结果